/**
 * jCarousel - Riding carousels with jQuery
 *   http://sorgalla.com/jcarousel/
 *
 * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Built on top of the jQuery library
 *   http://jquery.com
 *
 * Inspired by the "Carousel Component" by Bill Scott
 *   http://billwscott.com/carousel/
 */

(function($) {
		/**
		 * Creates a carousel for all matched elements.
		 *
		 * @example $("#mycarousel").jcarousel();
		 * @before <ul id="mycarousel" class="jcarousel-skin-name"><li>First item</li><li>Second item</li></ul>
		 * @result
		 *
		 * <div class="jcarousel-skin-name">
		 *   <div class="jcarousel-container">
		 *     <div disabled="disabled" class="jcarousel-prev jcarousel-prev-disabled"></div>
		 *     <div class="jcarousel-next"></div>
		 *     <div class="jcarousel-clip">
		 *       <ul class="jcarousel-list">
		 *         <li class="jcarousel-item-1">First item</li>
		 *         <li class="jcarousel-item-2">Second item</li>
		 *       </ul>
		 *     </div>
		 *   </div>
		 * </div>
		 *
		 * @name jcarousel
		 * @type jQuery
		 * @param Hash o A set of key/value pairs to set as configuration properties.
		 * @cat Plugins/jCarousel
		 */
		$.fn.jcarousel = function(o) {
				return this.each(function() {
						new $jc(this, o);
				});
		};

		// Default configuration properties.
		var defaults = {
				vertical: false,
				start: 1,
				offset: 1,
				size: null,
				scroll: 3,
				visible: null,
				animation: 'normal',
				easing: 'swing',
				auto: 0,
				wrap: null,
				initCallback: null,
				reloadCallback: null,
				itemLoadCallback: null,
				itemFirstInCallback: null,
				itemFirstOutCallback: null,
				itemLastInCallback: null,
				itemLastOutCallback: null,
				itemVisibleInCallback: null,
				itemVisibleOutCallback: null,
				buttonNextHTML: '<div></div>',
				buttonPrevHTML: '<div></div>',
				buttonNextEvent: 'click',
				buttonPrevEvent: 'click',
				buttonNextCallback: null,
				buttonPrevCallback: null
		};

		/**
		 * The jCarousel object.
		 *
		 * @constructor
		 * @name $.jcarousel
		 * @param Object e The element to create the carousel for.
		 * @param Hash o A set of key/value pairs to set as configuration properties.
		 * @cat Plugins/jCarousel
		 */
		$.jcarousel = function(e, o) {     
				this.options    = $.extend({}, defaults, o || {});

				this.locked     = false;

				this.container  = null;
				this.clip       = null;
				this.list       = null;
				this.buttonNext = null;
				this.buttonPrev = null;

				this.wh = !this.options.vertical ? 'width' : 'height';
				this.lt = !this.options.vertical ? 'left' : 'top';

				// Extract skin class
				var skin = '', split = e.className.split(' ');

				for (var i = 0; i < split.length; i++) {
						if (split[i].indexOf('jcarousel-skin') != -1) {
								$(e).removeClass(split[i]);
								var skin = split[i];
								break;
						}
				}

				if (e.nodeName == 'UL' || e.nodeName == 'OL') {
						this.list = $(e);
						this.container = this.list.parent();

						if (this.container.hasClass('jcarousel-clip')) {
								if (!this.container.parent().hasClass('jcarousel-container'))
										this.container = this.container.wrap('<div></div>');

								this.container = this.container.parent();
						} else if (!this.container.hasClass('jcarousel-container'))
								this.container = this.list.wrap('<div></div>').parent();
				} else {
						this.container = $(e);
						this.list = $(e).find('>ul,>ol,div>ul,div>ol');
				}

				if (skin != '' && this.container.parent()[0].className.indexOf('jcarousel-skin') == -1)
					this.container.wrap('<div class=" '+ skin + '"></div>');

				this.clip = this.list.parent();

				if (!this.clip.length || !this.clip.hasClass('jcarousel-clip'))
						this.clip = this.list.wrap('<div></div>').parent();

				this.buttonPrev = $('.jcarousel-prev', this.container);

				if (this.buttonPrev.size() == 0 && this.options.buttonPrevHTML != null)
						this.buttonPrev = this.clip.before(this.options.buttonPrevHTML).prev();

				this.buttonPrev.addClass(this.className('jcarousel-prev'));

				this.buttonNext = $('.jcarousel-next', this.container);

				if (this.buttonNext.size() == 0 && this.options.buttonNextHTML != null)
						this.buttonNext = this.clip.before(this.options.buttonNextHTML).prev();

				this.buttonNext.addClass(this.className('jcarousel-next'));

				this.clip.addClass(this.className('jcarousel-clip'));
				this.list.addClass(this.className('jcarousel-list'));
				this.container.addClass(this.className('jcarousel-container'));

				var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
				var li = this.list.children('li');

				var self = this;

				if (li.size() > 0) {
						var wh = 0, i = this.options.offset;
						li.each(function() {
								self.format(this, i++);
								wh += self.dimension(this, di);
						});

						this.list.css(this.wh, wh + 'px');

						// Only set if not explicitly passed as option
						if (!o || o.size === undefined)
								this.options.size = li.size();
				}
																									
				// For whatever reason, .show() does not work in Safari...
				this.container.css('display', 'block');
				this.buttonNext.css('display', 'block');
				this.buttonPrev.css('display', 'block');

				this.funcNext   = function() { self.next(); };
				this.funcPrev   = function() { self.prev(); };
				this.funcResize = function() { self.reload(); };

				if (this.options.initCallback != null)
						this.options.initCallback(this, 'init');
																
				if ($.browser.safari) {  
						this.buttons(false, false); 	  
						$(window).bind('load', function() { self.setup(); });
				} else
						this.setup();
		};

		// Create shortcut for internal use
		var $jc = $.jcarousel;

		$jc.fn = $jc.prototype = {
				jcarousel: '0.2.3'
		};

		$jc.fn.extend = $jc.extend = $.extend;

		$jc.fn.extend({
				/**
				 * Setups the carousel.
				 *
				 * @name setup
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				setup: function() {        
						this.first     = null;
						this.last      = null;
						this.prevFirst = null;
						this.prevLast  = null;
						this.animating = false;
						this.timer     = null;
						this.tail      = null;
						this.inTail    = false;

						if (this.locked)
								return;

						this.list.css(this.lt, this.pos(this.options.offset) + 'px');
						var p = this.pos(this.options.start);
						this.prevFirst = this.prevLast = null;
						this.animate(p, false);        

						$(window).unbind('resize', this.funcResize).bind('resize', this.funcResize);
				},

				/**
				 * Clears the list and resets the carousel.
				 *
				 * @name reset
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				reset: function() {
						this.list.empty();

						this.list.css(this.lt, '0px');
						this.list.css(this.wh, '10px');

						if (this.options.initCallback != null)
								this.options.initCallback(this, 'reset');

						this.setup();
				},

				/**
				 * Reloads the carousel and adjusts positions.
				 *
				 * @name reload
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				reload: function() {
						if (this.tail != null && this.inTail)
								this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + this.tail);

						this.tail   = null;
						this.inTail = false;

						if (this.options.reloadCallback != null)
								this.options.reloadCallback(this);

						if (this.options.visible != null) {
								var self = this;
								var di = Math.ceil(this.clipping() / this.options.visible), wh = 0, lt = 0;
								$('li', this.list).each(function(i) {
										wh += self.dimension(this, di);
										if (i + 1 < self.first)
												lt = wh;
								});

								this.list.css(this.wh, wh + 'px');
								this.list.css(this.lt, -lt + 'px');
						}

						this.scroll(this.first, false);
				},

				/**
				 * Locks the carousel.
				 *
				 * @name lock
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				lock: function() {
						this.locked = true;
						this.buttons();
				},

				/**
				 * Unlocks the carousel.
				 *
				 * @name unlock
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				unlock: function() {
						this.locked = false;
						this.buttons();
				},

				/**
				 * Sets the size of the carousel.
				 *
				 * @name size
				 * @type undefined
				 * @param Number s The size of the carousel.
				 * @cat Plugins/jCarousel
				 */
				size: function(s) {
						if (s != undefined) {
								this.options.size = s;
								if (!this.locked)
										this.buttons();
						}

						return this.options.size;
				},

				/**
				 * Checks whether a list element exists for the given index (or index range).
				 *
				 * @name get
				 * @type bool
				 * @param Number i The index of the (first) element.
				 * @param Number i2 The index of the last element.
				 * @cat Plugins/jCarousel
				 */
				has: function(i, i2) {
						if (i2 == undefined || !i2)
								i2 = i;

						if (this.options.size !== null && i2 > this.options.size)
							i2 = this.options.size;

						for (var j = i; j <= i2; j++) {
								var e = this.get(j);
								if (!e.length || e.hasClass('jcarousel-item-placeholder'))
										return false;
						}

						return true;
				},

				/**
				 * Returns a jQuery object with list element for the given index.
				 *
				 * @name get
				 * @type jQuery
				 * @param Number i The index of the element.
				 * @cat Plugins/jCarousel
				 */
				get: function(i) {
						return $('.jcarousel-item-' + i, this.list);
				},

				/**
				 * Adds an element for the given index to the list.
				 * If the element already exists, it updates the inner html.
				 * Returns the created element as jQuery object.
				 *
				 * @name add
				 * @type jQuery
				 * @param Number i The index of the element.
				 * @param String s The innerHTML of the element.
				 * @cat Plugins/jCarousel
				 */
				add: function(i, s) {
						var e = this.get(i), old = 0, add = 0;

						if (e.length == 0) {
								var c, e = this.create(i), j = $jc.intval(i);
								while (c = this.get(--j)) {
										if (j <= 0 || c.length) {
												j <= 0 ? this.list.prepend(e) : c.after(e);
												break;
										}
								}
						} else
								old = this.dimension(e);

						e.removeClass(this.className('jcarousel-item-placeholder'));
						typeof s == 'string' ? e.html(s) : e.empty().append(s);

						var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
						var wh = this.dimension(e, di) - old;

						if (i > 0 && i < this.first)
								this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - wh + 'px');

						this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) + wh + 'px');

						return e;
				},

				/**
				 * Removes an element for the given index from the list.
				 *
				 * @name remove
				 * @type undefined
				 * @param Number i The index of the element.
				 * @cat Plugins/jCarousel
				 */
				remove: function(i) {
						var e = this.get(i);

						// Check if item exists and is not currently visible
						if (!e.length || (i >= this.first && i <= this.last))
								return;

						var d = this.dimension(e);

						if (i < this.first)
								this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + d + 'px');

						e.remove();

						this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) - d + 'px');
				},

				/**
				 * Moves the carousel forwards.
				 *
				 * @name next
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				next: function() {        
						this.stopAuto();

						if (this.tail != null && !this.inTail)
								this.scrollTail(false);
						else
								this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'last') && this.options.size != null && this.last == this.options.size) ? 1 : this.first + this.options.scroll);
								
						// SEPTIME 04-01-2010
						// Update page num
						setPageNum(this.first);
				},

				/**
				 * Moves the carousel backwards.
				 *
				 * @name prev
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				prev: function() {
						this.stopAuto();

						if (this.tail != null && this.inTail)
								this.scrollTail(true);
						else
								this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'first') && this.options.size != null && this.first == 1) ? this.options.size : this.first - this.options.scroll);
								
						// SEPTIME 04-01-2010
						// Update page num
						setPageNum(this.first);
				},

				/**
				 * Scrolls the tail of the carousel.
				 *
				 * @name scrollTail
				 * @type undefined
				 * @param Bool b Whether scroll the tail back or forward.
				 * @cat Plugins/jCarousel
				 */
				scrollTail: function(b) {
						if (this.locked || this.animating || !this.tail)
								return;

						var pos  = $jc.intval(this.list.css(this.lt));

						!b ? pos -= this.tail : pos += this.tail;
						this.inTail = !b;

						// Save for callbacks
						this.prevFirst = this.first;
						this.prevLast  = this.last;

						this.animate(pos);
				},

				/**
				 * Scrolls the carousel to a certain position.
				 *
				 * @name scroll
				 * @type undefined
				 * @param Number i The index of the element to scoll to.
				 * @param Bool a Flag indicating whether to perform animation.
				 * @cat Plugins/jCarousel
				 */
				scroll: function(i, a) {
						if (this.locked || this.animating)
								return;

						this.animate(this.pos(i), a);   
						
				},

				/**
				 * Prepares the carousel and return the position for a certian index.
				 *
				 * @name pos
				 * @type Number
				 * @param Number i The index of the element to scoll to.
				 * @cat Plugins/jCarousel
				 */
				pos: function(i) {
						if (this.locked || this.animating)
								return;

						i = $jc.intval(i);
						if (this.options.wrap != 'circular')
								i = i < 1 ? 1 : (this.options.size && i > this.options.size ? this.options.size : i);

						var back = this.first > i;
						var pos  = $jc.intval(this.list.css(this.lt));

						// Create placeholders, new list width/height
						// and new list position
						var f = this.options.wrap != 'circular' && this.first <= 1 ? 1 : this.first;
						var c = back ? this.get(f) : this.get(this.last);
						var j = back ? f : f - 1;
						var e = null, l = 0, p = false, d = 0;

						while (back ? --j >= i : ++j < i) {
								e = this.get(j);
								p = !e.length;
								if (e.length == 0) {
										e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
										c[back ? 'before' : 'after' ](e);
								}

								c = e;
								d = this.dimension(e);

								if (p)
										l += d;

								if (this.first != null && (this.options.wrap == 'circular' || (j >= 1 && (this.options.size == null || j <= this.options.size))))
										pos = back ? pos + d : pos - d;
						}

						// Calculate visible items
						var clipping = this.clipping();
						var cache = [];
						var visible = 0, j = i, v = 0;
						var c = this.get(i - 1);

						while (++visible) {
								e = this.get(j);
								p = !e.length;
								if (e.length == 0) {
										e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
										// This should only happen on a next scroll
										c.length == 0 ? this.list.prepend(e) : c[back ? 'before' : 'after' ](e);
								}

								c = e;
								var d = this.dimension(e);
								if (d == 0) {
										alert('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...');
										return 0;
								}

								if (this.options.wrap != 'circular' && this.options.size !== null && j > this.options.size)
										cache.push(e);
								else if (p)
										l += d;

								v += d;

								if (v >= clipping)
										break;

								j++;
						}

						 // Remove out-of-range placeholders
						for (var x = 0; x < cache.length; x++)
								cache[x].remove();

						// Resize list
						if (l > 0) {
								this.list.css(this.wh, this.dimension(this.list) + l + 'px');

								if (back) {
										pos -= l;
										this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - l + 'px');
								}
						}

						// Calculate first and last item
						var last = i + visible - 1;
						if (this.options.wrap != 'circular' && this.options.size && last > this.options.size)
								last = this.options.size;

						if (j > last) {
								visible = 0, j = last, v = 0;
								while (++visible) {
										var e = this.get(j--);
										if (!e.length)
												break;
										v += this.dimension(e);
										if (v >= clipping)
												break;
								}
						}

						var first = last - visible + 1;
						if (this.options.wrap != 'circular' && first < 1)
								first = 1;

						if (this.inTail && back) {
								pos += this.tail;
								this.inTail = false;
						}

						this.tail = null;
						if (this.options.wrap != 'circular' && last == this.options.size && (last - visible + 1) >= 1) {
								var m = $jc.margin(this.get(last), !this.options.vertical ? 'marginRight' : 'marginBottom');
								if ((v - m) > clipping)
										this.tail = v - clipping - m;
						}

						// Adjust position
						while (i-- > first)
								pos += this.dimension(this.get(i));

						// Save visible item range
						this.prevFirst = this.first;
						this.prevLast  = this.last;
						this.first     = first;
						this.last      = last;

						return pos;
				},

				/**
				 * Animates the carousel to a certain position.
				 *
				 * @name animate
				 * @type undefined
				 * @param mixed p Position to scroll to.
				 * @param Bool a Flag indicating whether to perform animation.
				 * @cat Plugins/jCarousel
				 */
				animate: function(p, a) {     
						if (this.locked || this.animating)
								return;

						this.animating = true;

						var self = this;
						var scrolled = function() {
								self.animating = false;

								if (p == 0)
										self.list.css(self.lt,  0);

								if (self.options.wrap == 'both' || self.options.wrap == 'last' || self.options.size == null || self.last < self.options.size)
										self.startAuto();

								self.buttons();
								self.notify('onAfterAnimation');
						};

						this.notify('onBeforeAnimation');

						// Animate
						if (!this.options.animation || a == false) {
								this.list.css(this.lt, p + 'px');
								scrolled();
						} else {
								var o = !this.options.vertical ? {'left': p} : {'top': p};
								this.list.animate(o, this.options.animation, this.options.easing, scrolled);
						}
						
				},

				/**
				 * Starts autoscrolling.
				 *
				 * @name auto
				 * @type undefined
				 * @param Number s Seconds to periodically autoscroll the content.
				 * @cat Plugins/jCarousel
				 */
				startAuto: function(s) {    
						if (s != undefined)
								this.options.auto = s;

						if (this.options.auto == 0)
								return this.stopAuto();

						if (this.timer != null)
								return;

						var self = this;
						this.timer = setTimeout(function() { self.next(); }, this.options.auto * 1000);
				},

				/**
				 * Stops autoscrolling.
				 *
				 * @name stopAuto
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				stopAuto: function() {
						if (this.timer == null)
								return;

						clearTimeout(this.timer);
						this.timer = null;
				},

				/**
				 * Sets the states of the prev/next buttons.
				 *
				 * @name buttons
				 * @type undefined
				 * @cat Plugins/jCarousel
				 */
				buttons: function(n, p) {
						if (n == undefined || n == null) {
								var n = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'first') || this.options.size == null || this.last < this.options.size);
								if (!this.locked && (!this.options.wrap || this.options.wrap == 'first') && this.options.size != null && this.last >= this.options.size)
										n = this.tail != null && !this.inTail;
						}

						if (p == undefined || p == null) {
								var p = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'last') || this.first > 1);
								if (!this.locked && (!this.options.wrap || this.options.wrap == 'last') && this.options.size != null && this.first == 1)
										p = this.tail != null && this.inTail;
						}

						var self = this;

						this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);
						this.buttonPrev[p ? 'bind' : 'unbind'](this.options.buttonPrevEvent, this.funcPrev)[p ? 'removeClass' : 'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled', p ? false : true);

						if (this.buttonNext.length > 0 && (this.buttonNext[0].jcarouselstate == undefined || this.buttonNext[0].jcarouselstate != n) && this.options.buttonNextCallback != null) {
								this.buttonNext.each(function() { self.options.buttonNextCallback(self, this, n); });
								this.buttonNext[0].jcarouselstate = n;
						}

						if (this.buttonPrev.length > 0 && (this.buttonPrev[0].jcarouselstate == undefined || this.buttonPrev[0].jcarouselstate != p) && this.options.buttonPrevCallback != null) {
								this.buttonPrev.each(function() { self.options.buttonPrevCallback(self, this, p); });
								this.buttonPrev[0].jcarouselstate = p;
						}
				},

				notify: function(evt) {           
						var state = this.prevFirst == null ? 'init' : (this.prevFirst < this.first ? 'next' : 'prev');

						// Load items
						this.callback('itemLoadCallback', evt, state);

						if (this.prevFirst !== this.first) {
								this.callback('itemFirstInCallback', evt, state, this.first);
								this.callback('itemFirstOutCallback', evt, state, this.prevFirst);
						}

						if (this.prevLast !== this.last) {
								this.callback('itemLastInCallback', evt, state, this.last);
								this.callback('itemLastOutCallback', evt, state, this.prevLast);
						}

						this.callback('itemVisibleInCallback', evt, state, this.first, this.last, this.prevFirst, this.prevLast);
						this.callback('itemVisibleOutCallback', evt, state, this.prevFirst, this.prevLast, this.first, this.last);
						
				},

				callback: function(cb, evt, state, i1, i2, i3, i4) {
						if (this.options[cb] == undefined || (typeof this.options[cb] != 'object' && evt != 'onAfterAnimation'))
								return;

						var callback = typeof this.options[cb] == 'object' ? this.options[cb][evt] : this.options[cb];

						if (!$.isFunction(callback))
								return;

						var self = this;

						if (i1 === undefined)
								callback(self, state, evt);
						else if (i2 === undefined)
								this.get(i1).each(function() { callback(self, this, i1, state, evt); });
						else {
								for (var i = i1; i <= i2; i++)
										if (i !== null && !(i >= i3 && i <= i4))
												this.get(i).each(function() { callback(self, this, i, state, evt); });
						}
						
				},

				create: function(i) {
						return this.format('<li></li>', i);
				},

				format: function(e, i) {
						var $e = $(e).addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-' + i));
						$e.attr('jcarouselindex', i);
						return $e;
				},

				className: function(c) {
						return c + ' ' + c + (!this.options.vertical ? '-horizontal' : '-vertical');
				},

				dimension: function(e, d) {
						var el = e.jquery != undefined ? e[0] : e;

						var old = !this.options.vertical ?
								el.offsetWidth + $jc.margin(el, 'marginLeft') + $jc.margin(el, 'marginRight') :
								el.offsetHeight + $jc.margin(el, 'marginTop') + $jc.margin(el, 'marginBottom');

						if (d == undefined || old == d)
								return old;

						var w = !this.options.vertical ?
								d - $jc.margin(el, 'marginLeft') - $jc.margin(el, 'marginRight') :
								d - $jc.margin(el, 'marginTop') - $jc.margin(el, 'marginBottom');

						$(el).css(this.wh, w + 'px');

						return this.dimension(el);
				},

				clipping: function() {
						return !this.options.vertical ?
								this.clip[0].offsetWidth - $jc.intval(this.clip.css('borderLeftWidth')) - $jc.intval(this.clip.css('borderRightWidth')) :
								this.clip[0].offsetHeight - $jc.intval(this.clip.css('borderTopWidth')) - $jc.intval(this.clip.css('borderBottomWidth'));
				},

				index: function(i, s) {
						if (s == undefined)
								s = this.options.size;

						return Math.round((((i-1) / s) - Math.floor((i-1) / s)) * s) + 1;
				}
		});

		$jc.extend({
				/**
				 * Gets/Sets the global default configuration properties.
				 *
				 * @name defaults
				 * @descr Gets/Sets the global default configuration properties.
				 * @type Hash
				 * @param Hash d A set of key/value pairs to set as configuration properties.
				 * @cat Plugins/jCarousel
				 */
				defaults: function(d) {
						return $.extend(defaults, d || {});
				},

				margin: function(e, p) {
						if (!e)
								return 0;

						var el = e.jquery != undefined ? e[0] : e;

						if (p == 'marginRight' && $.browser.safari) {
								var old = {'display': 'block', 'float': 'none', 'width': 'auto'}, oWidth, oWidth2;

								$.swap(el, old, function() { oWidth = el.offsetWidth; });

								old['marginRight'] = 0;
								$.swap(el, old, function() { oWidth2 = el.offsetWidth; });

								return oWidth2 - oWidth;
						}

						return $jc.intval($.css(el, p));
				},

				intval: function(v) {
						v = parseInt(v);
						return isNaN(v) ? 0 : v;
				}
		});

})(jQuery);
