
/*
 * aciScrollBar jQuery Plugin v1.2
 * http://acoderinsights.ro
 *
 * Copyright (c) 2011, Dragos Ursu
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Needs jQuery Library http://jquery.com and
 * MouseWheel Plugin (for mouse wheel support) http://brandonaaron.net
 *
 * Date: Fri Oct 21 20:15 2011 +0200
 */

(function($){

// mainly for event unbinding
this._namespace = '.aciScrollBar';

// keep current control index
$.aciScrollBar = {
	index: 0
};

$.fn.aciScrollBar = function(options, data){
	// add custom override for scrollLeft & scrollTop
	if (this.data('customUi' + _namespace))
	{
		this.scrollLeft = function(){
			var container = this.find('.aciSb_cnt:first');
			return container.scrollLeft();
		};
		this.scrollTop = function(){
			var container = this.find('.aciSb_cnt:first');
			return container.scrollTop();
		};
	}
	if (typeof(options) == 'string')
	{
		return $(this)._aciScrollBar(options, data);
	}
	return this.each(function(){
		return $(this)._aciScrollBar(options, data);
	});
};

$.fn._aciScrollBar = function(options, data){

var theObj = this;

// available (default) options

var _options = $.extend({
	delta: 40,               				// size of a line by height (in pixels)
	lineDelay: 40,         			  // delay of the first line scroll before the scoll will continue
	lineTimer: 20,           				// delay of the continuous scrolling (by lines)
	pageDelay: 40,          				// delay of the first page scroll before the scoll will continue
	pageTimer: 20,          				// delay of the continuous scrolling (by pages)
	bindMouse: false,         				// should handle mouse events in the content?
	bindKeyboard: true,      				// should handle keyboard events?
	resizable: false,        				// it is a resisable control?
	position: 'bottomright', 				// where we should have the scrollbars? (combination of two words from: top/left/bottom/right)
	verticalBar: 'upbardown', 			// what is the button order for the vertical bar? (combination of up/bar/down or none)
	horizontalBar: 'leftbarright',	// what is the button order for the horizontal bar? (combination of left/bar/right or none)
	smoothScroll: false,     				// should we use smoth scrolling?
	cssClass: 'w7'           				// the CSS class name (the .css file must be loaded before the init)
}, options || {});

// get grip size (if fixed size)

var _gripSize = function (cssClass)
{
	var dddd = $(".aciSb_dddd");
	if (dddd.length == 0)
	{
		dddd = $(document.createElement('div'));
		dddd.addClass("aciSb_dddd").css({width:0,height:0,position:"relative",overflow:"hidden"});
		$(document.body).append(dddd);
		var tmp = $(document.createElement('div'));
		tmp.addClass("aciSb_grip " + cssClass);
		dddd.append(tmp);
	}
	else
	{
		var tmp = dddd.find("div");
		tmp.attr("class", "aciSb_grip " + cssClass);
	}
	$(theObj).data("_grip_w", tmp.width());
  $(theObj).data("_grip_h", tmp.height());
};

// init based on options

var _initUi = function(){
	if ((typeof(options) == 'object') || ((typeof(options) == 'boolean') && options))
	{
		// init with event handling & skin
		_customUi();
		// remember options
		$(theObj).data("options" + _namespace, _options);		
	}
	if ((typeof(options) == 'boolean') && !options)
	{
		// init with event handling (no skin)
		_defaultUi();
		// remember options
		$(theObj).data("options" + _namespace, _options);
	}
	// process custom request	
	if (typeof(options) == 'string')
	{
		if ($(theObj).data('customUi' + _namespace))
		{
			// we get here is this was skinned
			switch (options)
			{
				case 'skinned':
				  // is this skinned?
					return true;
				case 'container':
				  // return content container element
					return $(theObj).find('.aciSb_cnt:first');
				case 'verticalBar':
				  // return the vertical bar element
					return $(theObj).find('.aciSb_bar_v:last');
				case 'horizontalBar':
				  // return the horizontal bar element
					return $(theObj).find('.aciSb_bar_h:last');
				case 'sizer':
				  // return the sizer element
					return $(theObj).find('.aciSb_resize:last');
				case 'setClass':
				  // set the CSS class name
					if ((typeof(data) == 'string') && ($(theObj).data('cssClass' + _namespace) != data))
					{
						_gripSize(data);
						_setClass($(theObj).data('cssClass' + _namespace), data);
						$(theObj).data('cssClass' + _namespace, data).trigger('resize', {forced:true});
					}
					break;
				case 'getClass':
  				// get CSS class name
				  return $(theObj).data('cssClass' + _namespace);
				case 'options':
				  // get options
				  return $(theObj).data("options" + _namespace);
				case 'destroy':
				  // destroy the control (revert to the default)
					_destroyUi();
			}
		}
		else
		{
			switch (options)
			{
				case 'skinned':
  				// is this skinned?
					return false;
				case 'container':
				  // return content container element
					return $(theObj);
				case 'destroy':
				  // destroy the control (revert to the default)
					_destroyUi();
			}
		}
	}
  // by default return this object
  return theObj;
};

var _replaceClass = function (obj, oldClass, newClass)
{
	obj.each(function(){
		$(this).attr("class", $(this).attr("class").replace(oldClass, newClass));
	});
};

var _setClass = function (oldClass, newClass)
{
	_replaceClass($(theObj), oldClass, newClass);
	_replaceClass($(theObj).find('.aciSb_bar_v:last, .aciSb_bar_v:last *'), oldClass, newClass);
	_replaceClass($(theObj).find('.aciSb_bar_h:last, .aciSb_bar_h:last *'), oldClass, newClass);
	_replaceClass($(theObj).find('.aciSb_resize:last'), oldClass, newClass);
  _replaceClass($(theObj).find('.aciSb_cnt:first'), oldClass, newClass);
};

// destroy current UI

var _destroyUi = function(){
	// for default UI remove the event handling
	if ($(theObj).data('defaultUi' + _namespace))
	{
		$(theObj).data('defaultUi' + _namespace, false);
		$(theObj).unbind(_namespace);
	}
	// for custom UI remove the event handling & skin
	if ($(theObj).data('customUi' + _namespace))
	{
		var cnt = $(theObj).find('.aciSb_cnt:first');
		// to compute new position
		var height = cnt.get(0).scrollHeight;
		var width = cnt.get(0).scrollWidth;
		var top = cnt.scrollTop();
		var left = cnt.scrollLeft();
		$(theObj).data('customUi' + _namespace, false);
		var index = $(theObj).data('index' + _namespace);
		$('html').unbind(_namespace + '-' + index);
		$(theObj).unbind(_namespace);
		$(theObj).find('.aciSb_bar_v:last').remove();
		$(theObj).find('.aciSb_bar_h:last').remove();
		$(theObj).find('.aciSb_resize:last').remove();
		cnt.children().unwrap();
		$(theObj).removeClass('aciScrollBar ' + $(theObj).data('cssClass' + _namespace)).css('overflow', $(theObj).data('overflow' + _namespace));
    // reposition where it was
		$(theObj).get(0).scrollTop = Math.round($(theObj).get(0).scrollHeight * top / height);
		$(theObj).get(0).scrollLeft = Math.round($(theObj).get(0).scrollWidth * left / width);
	}
}; // end _destroyUi

// init default UI

var _defaultUi = function(){
	if ($(theObj).data('defaultUi' + _namespace))
	{
		// return if already initialised in this mode
		return;
	}
	// first make sure we destroy the control
	_destroyUi();
	$(theObj).data('defaultUi' + _namespace, true);
	var _lineUp = function(){
		var pos = $(theObj).scrollTop() - _options.delta;
		$(theObj).get(0).scrollTop = Math.max(pos, 0);
	};
	var _pageUp = function(){
		var pos = $(theObj).scrollTop() - $(theObj).height();
		$(theObj).get(0).scrollTop = Math.max(pos, 0);
	};
	var _lineDown = function(){
		var pos = $(theObj).scrollTop() + _options.delta;
		$(theObj).get(0).scrollTop = Math.max(pos, 0);
	};
	var _pageDown = function(){
		var pos = $(theObj).scrollTop() + $(theObj).height();
		$(theObj).get(0).scrollTop = Math.max(pos, 0);
	};
	var _lineLeft = function(){
		var pos = $(theObj).scrollLeft() - _options.delta;
		$(theObj).get(0).scrollLeft = Math.max(pos, 0);
	};
	var _pageLeft = function(){
		var pos = $(theObj).scrollLeft() - $(theObj).width();
		$(theObj).get(0).scrollLeft = Math.max(pos, 0);
	};
	var _lineRight = function(){
		var pos = $(theObj).scrollLeft() + _options.delta;
		$(theObj).get(0).scrollLeft = Math.max(pos, 0);
	};
	var _pageRight = function(){
		var pos = $(theObj).scrollLeft() + $(theObj).width();
		$(theObj).get(0).scrollLeft = Math.max(pos, 0);
	};
	// keep focus state
	var _focus = false;
	if (_options.bindKeyboard)
	{
		// keyboard handling
		$(theObj).bind('keydown' + _namespace, function(e){
			if (!_focus)
			{
				// do not handle if we do not have focus
				return;
			}
			switch (e.which)
			{
				case 38: // up
					_lineUp();
					return false;
				case 40: // down
					_lineDown();
					return false;
				case 37: // left
					_lineLeft();
					return false;
				case 39: // right
					_lineRight();
					return false;
				case 33: // pgup
					_pageUp();
					return false;
				case 34: // pgdown
					_pageDown();
					return false;
				case 36: // home
					this.scrollTop = 0;
					this.scrollLeft = 0;
					return false;
				case 35: // end
					this.scrollTop = this.scrollHeight;
					this.scrollLeft = 0;
					return false;	
			}
		});
	}
	// get contained element position
	var _elementPos = function(obj){
		var pos = obj.position();
		var top = $(theObj).scrollTop() + pos.top;
		var left = $(theObj).scrollLeft() + pos.left;
		return {'top':top, 'left':left};
	};
	// bind events to respond to
	$(theObj).bind('focus' + _namespace, function(){
		_focus = true;
	}).bind('blur' + _namespace, function(){
		_focus = false;
	}).bind('scrollup' + _namespace, function(){
		_lineUp();
		return false;
	}).bind('pageup' + _namespace, function(){
		_pageUp();
		return false;
	}).bind('scrolldown' + _namespace, function(){
		_lineDown();
		return false;
	}).bind('pagedown' + _namespace, function(){
		_pageDown();
		return false;
	}).bind('scrollleft' + _namespace, function(){
		_lineLeft();
		return false;
	}).bind('pageleft' + _namespace, function(){
		_pageLeft();
		return false;
	}).bind('scrollright' + _namespace, function(){
		_lineRight();
		return false;
	}).bind('pageright' + _namespace, function(){
		_pageRight();
		return false;
	}).bind('scrollto' + _namespace, function(e, data){
		// scroll to top/left (with animation)
		if (typeof(data) != 'object')
		{
			return false;
		}
		if (typeof(data.top) != 'undefined')
		{
			var top = data.top;
			if (typeof(top) == 'string')
			{
				var ret = null;
				var rex = new RegExp('^([0-9]+)%$');
				if (ret = rex.exec(top))
				{
					top = Math.round((this.scrollHeight - $(this).height()) * parseFloat(ret[1]) / 100);
				}
				else	
				{
					rex = new RegExp('^([0-9]+)$');
					if (ret = rex.exec(top))
					{
						top = Math.abs(parseInt(ret[1]));
					}
				}
			}
			if (data.animate)
			{
				$(this).animate({'scrollTop': top}, data.duration, data.animate);
			}
			else
			{
				this.scrollTop = Math.max(top, 0);
			}
		}
		if (typeof(data.left) != 'undefined')
		{
			var left = data.left;
			if (typeof(left) == 'string')
			{
				var ret = null;
				var rex = new RegExp('^([0-9]+)%$');
				if (ret = rex.exec(left))
				{
					left = Math.round((this.scrollWidth - $(this).width()) * parseFloat(ret[1]) / 100);
				}
				else	
				{
					rex = new RegExp('^([0-9]+)$');
					if (ret = rex.exec(left))
					{
						left = Math.abs(parseInt(ret[1]));
					}
				}
			}
			if (data.animate)
			{
				$(this).animate({'scrollLeft': left}, data.duration, data.animate);
			}
			else			
			{
				this.scrollLeft = Math.max(left, 0);
			}
		}
		return false;
	}).bind('goto' + _namespace, function(e, data){
		// scroll to a element inside the content (with animation)
		if ((typeof(data) != 'object') || (typeof(data.element) == 'undefined'))
		{
			return false;
		}
		var obj = $(data.element);
		if (obj.get(0) && $(theObj).has(obj.get(0)))
		{
			var pos = _elementPos(obj);
			var center = ((typeof(data.center) != 'boolean') ? true : data.center);
			if (center)
			{
				if (obj.width() < $(theObj).width())
				{
					pos.left -= Math.round($(theObj).width() / 2 - obj.width() / 2);
				}
				if (obj.height() < $(theObj).height())
				{
					pos.top -= Math.round($(theObj).height() / 2 - obj.height() / 2);
				}
			}
			var offsety = (data.offsety ? parseInt(data.offsety) : 0);
			if (Math.abs($(theObj).scrollTop() - Math.abs(pos.top)) >= offsety)
			{
				if (data.animate)
				{
					$(this).animate({'scrollTop': pos.top}, data.duration, data.animate);
				}
				else	
				{
					this.scrollTop = Math.max(pos.top, 0);
				}
			}
			var offsetx = (data.offsetx ? parseInt(data.offsetx) : 0);
			if (Math.abs($(theObj).scrollLeft() - Math.abs(pos.left)) >= offsetx)
			{
				if (data.animate)
				{
					$(this).animate({'scrollLeft': pos.left}, data.duration, data.animate);
				}
				else
				{
					this.scrollLeft = Math.max(pos.left, 0);
				}
			}
		}
		return false;
	});
}; // end _defaultUi

// init custom UI	

var _customUi = function(){
	if ($(theObj).data('customUi' + _namespace))
	{
		// return if already initialised in this mode
		return;
	}

	// only init for the right elements
	if (($(theObj).css('overflow') != 'auto') && ($(theObj).css('overflow') != 'scroll'))
	{
		// return if overflow is not "auto" or "scoll"
		return;
	}

  // first make sure we destroy the control
	_destroyUi();
	$(theObj).data('customUi' + _namespace, true);
	
	// update control index so we can unbind window events later
	var _index = $(theObj).data('index' + _namespace);
	
	if (!_index)
	{
		//$.aciScrollBar.index++;
		$(theObj).data('index' + _namespace, $.aciScrollBar.index);
		_index = $.aciScrollBar.index;
	}
	
	// trigger init event
	$(theObj).trigger('init');

	$(theObj).data('overflow' + _namespace, $(theObj).css('overflow'));

  // should we hide the scollbars if not required?
	var _hide = ($(theObj).css('overflow') == 'auto') && !_options.resizable;

	// save for later
	var _scroll = {
		height: $(theObj).get(0).scrollHeight,
	  width: $(theObj).get(0).scrollWidth,
		top: $(theObj).scrollTop(),
		left: $(theObj).scrollLeft()
	};
		
	$(theObj).get(0).scrollLeft = 0;
	$(theObj).get(0).scrollTop = 0;

	$(theObj).data('cssClass' + _namespace, _options.cssClass);

	_gripSize(_options.cssClass);

	$(theObj).css('overflow', 'hidden').addClass('aciScrollBar ' + _options.cssClass);

	// add an extra container
	$(theObj).wrapInner('<div class="aciSb_cnt ' + _options.cssClass + '" unselectable="on"></div>');
	var _container = $(theObj).find('.aciSb_cnt:first');

	// init position
	_container.get(0).scrollLeft = 0;
	_container.get(0).scrollTop = 0;

	var _setElement = function(tag, style, parent){
		var obj = $(document.createElement(tag));
		obj.addClass(style + " " + _options.cssClass).attr('unselectable', 'on').css({"-moz-user-select":"none","-webkit-user-select":"none"});
		parent.append(obj);
		return obj;
	};

	// add all bars elements (sizer too)
	
	var _bar_v = _setElement('div', 'aciSb_bar_v', theObj);
	var _arrow_t = _setElement('div', 'aciSb_arrow_t', _bar_v);
	var _space_t = _setElement('div', 'aciSb_space_t', _bar_v);
	var _track_v = _setElement('div', 'aciSb_track_v', _bar_v);
	var _track_t = _setElement('div', 'aciSb_track_t', _track_v);
	var _drag_vc = _setElement('div', 'aciSb_drag_vc', _track_v);
	var _drag_t = _setElement('div', 'aciSb_drag_t', _drag_vc);
	var _drag_v = _setElement('div', 'aciSb_drag_v', _drag_vc);
	var _drag_vg = _setElement('div', 'aciSb_drag_vg', _drag_v);
	var _drag_b = _setElement('div', 'aciSb_drag_b', _drag_vc);
	var _track_b = _setElement('div', 'aciSb_track_b', _track_v);
	var _space_b = _setElement('div', 'aciSb_space_b', _bar_v);
	var _arrow_b = _setElement('div', 'aciSb_arrow_b', _bar_v);
	
	var _bar_h = _setElement('div', 'aciSb_bar_h', theObj);
	var _arrow_l = _setElement('div', 'aciSb_arrow_l', _bar_h);
	var _space_l = _setElement('div', 'aciSb_space_l', _bar_h);
	var _track_h = _setElement('div', 'aciSb_track_h', _bar_h);
	var _track_l = _setElement('div', 'aciSb_track_l', _track_h);
	var _drag_hc = _setElement('div', 'aciSb_drag_hc', _track_h);
	var _drag_l = _setElement('div', 'aciSb_drag_l', _drag_hc);
	var _drag_h = _setElement('div', 'aciSb_drag_h', _drag_hc);
	var _drag_hg = _setElement('div', 'aciSb_drag_hg', _drag_h);
	var _drag_r = _setElement('div', 'aciSb_drag_r', _drag_hc);
	var _track_r = _setElement('div', 'aciSb_track_r', _track_h);
	var _space_r = _setElement('div', 'aciSb_space_r', _bar_h);
	var _arrow_r = _setElement('div', 'aciSb_arrow_r', _bar_h);

	var _resize = _setElement('div', 'aciSb_resize', theObj);
	
	_bar_v.css("position", "absolute").find("*").css({"position":"absolute", "width":_bar_v.width() + "px"});
	_bar_h.css("position", "absolute").find("*").css({"position":"absolute", "height":_bar_h.height() + "px"});
	_resize.css({"position":"absolute", "width":_bar_v.width() + "px", "height":_bar_h.height() + "px"});
	
	// get vertical bar width
	_bar_v.width = function(){
		if (_bar_v.is(':hidden'))
		{
			return 0;
		}
		else	
		{
			return $(_bar_v).width();
		}
	};
	
	// get horizontal bar height
	_bar_h.height = function(){
		if (_bar_h.is(':hidden'))
		{
			return 0;
		}
		else
		{
			return $(_bar_h).height();
		}
	};
	
	var _contentWidth = function(){
		return _container.get(0).scrollWidth;
	};

	var _contentHeight = function(){
		return _container.get(0).scrollHeight;
	};

	// show/hide the bars as required
	var _initBars = function (){
		if (!_options.resizable && (_options.horizontalBar == "none"))
		{
			_bar_h.hide();
		}
		else
		{
			if (_contentWidth() <= $(theObj).width() - _bar_v.width())
			{
				if (!_options.resizable && _hide)
				{
					_bar_h.hide();
				}
				else
				{
					_bar_h.show();
				}
			}
			else
			{
				_bar_h.show();
			}
		}
		if (!_options.resizable && (_options.verticalBar == "none"))
		{
			_bar_v.hide();
		}
		else
		{
			if (_contentHeight() <= $(theObj).height() - _bar_h.height())
			{
				if (!_options.resizable && _hide)
				{
					_bar_v.hide();
				}
				else
				{
					_bar_v.show();
				}
			}
			else
			{
				_bar_v.show();
			}
		}
	};
	
	// get bar position (+1 bottom/right, -1 top/left)
	
	var _vert = 1;
	var _horz = 1;

	switch (_options.position)
	{
		case 'topleft':
		case 'lefttop':
			_vert = -1;
			_horz = -1;
			break;
		case 'topright':
		case 'righttop':
			_vert = 1;
			_horz = -1;
			break;
		case 'bottomleft':
		case 'leftbottom':
			_vert = -1;
			_horz = 1;
			break;
	}

	// (re)init the container (and the bars)
	var _initContainer = function(){
		_container.css('width', $(theObj).width() + 'px').css('height', $(theObj).height() + 'px');
		_initBars();
		_container.css('width', $(theObj).width() - _bar_v.width() + 'px').css('height', $(theObj).height() - _bar_h.height() + 'px');
		_initBars();
		_container.css('width', $(theObj).width() - _bar_v.width() + 'px').css('height', $(theObj).height() - _bar_h.height() + 'px');
		_bar_v.find("*").css("width", _bar_v.width() + "px");
		_bar_h.find("*").css("height", _bar_h.height() + "px");
		_resize.css({"width":_bar_v.width() + "px", "height":_bar_h.height() + "px"});
		var hsize = $(theObj).width() - _bar_v.width();
		var vsize = $(theObj).height() - _bar_h.height();
		var hpadd = parseInt($(theObj).css("padding-left"));
		var vpadd = parseInt($(theObj).css("padding-top"));
		_bar_v.css('height', vsize + 'px').css('left', ((_vert == 1) ? hsize : 0) + hpadd + 'px').css('top', ((_horz == 1) ? 0 : _bar_h.height()) + vpadd + 'px');
		_bar_h.css('width', hsize + 'px').css('top', ((_horz == 1) ? vsize : 0) + vpadd + 'px').css('left', ((_vert == 1) ? 0 : _bar_v.width()) + hpadd + 'px');
    // vertical bar
		switch (_options.verticalBar)
		{
			case "bar":
				_arrow_t.hide();
				_space_t.css("top", "0px");
				_track_v.css('height', vsize - _space_t.height() - _space_b.height() + 'px').css('top', _space_t.height() + 'px');
				_space_b.css("top", _bar_v.height() - _space_b.height() + "px");
				_arrow_b.hide();
				break;
			case "updownbar":
				_arrow_t.css('top', '0px');
				_arrow_b.css('top', _arrow_t.height() + 'px');
				_space_t.css("top", _arrow_t.height() + _arrow_b.height() + "px");
				_track_v.css('height', vsize - _arrow_t.height() - _space_t.height() - _space_b.height() - _arrow_b.height() + 'px').css('top', _arrow_t.height() + _arrow_b.height() + _space_t.height() + 'px');
				_space_b.css("top", _bar_v.height() - _space_b.height() + "px");
				break;
			case "barupdown":
				_space_t.css("top", "0px");
				_track_v.css('height', vsize - _arrow_t.height() - _space_t.height() - _space_b.height() - _arrow_b.height() + 'px').css('top', _space_t.height() + 'px');
				_space_b.css("top", _bar_v.height() - _arrow_t.height() - _arrow_b.height() - _space_b.height() + "px");
				_arrow_t.css('top', _bar_v.height() - _arrow_t.height() - _arrow_b.height() + 'px');
				_arrow_b.css('top', _bar_v.height() - _arrow_b.height() + 'px');
				break;
			default:	
				_arrow_t.css('top', '0px');
				_space_t.css("top", _arrow_t.height() + "px");
				_track_v.css('height', vsize - _arrow_t.height() - _space_t.height() - _space_b.height() - _arrow_b.height() + 'px').css('top', _arrow_t.height() + _space_t.height() + 'px');
				_space_b.css("top", _bar_v.height() - _arrow_b.height() - _space_b.height() + "px");
				_arrow_b.css('top', _bar_v.height() - _arrow_b.height() + 'px');
		}
    // horizontal bar
		switch (_options.horizontalBar)
		{
			case "bar":
				_arrow_l.hide();
				_space_l.css("left", "0px");
				_track_h.css('width', hsize - _space_l.width() - _space_r.width() + 'px').css('left', _space_l.width() + 'px');
				_space_r.css("left", _bar_h.width() - _space_r.width() + "px");
				_arrow_r.hide();
				break;
			case "leftrightbar":
				_arrow_l.css('left', '0px');
				_arrow_r.css('left', _arrow_l.width() + 'px');
				_space_l.css("left", _arrow_l.width() + _arrow_r.width() + "px");
				_track_h.css('width', hsize - _arrow_l.width() - _space_l.width() - _space_r.width() - _arrow_r.width() + 'px').css('left', _arrow_l.width() + _arrow_r.width() + _space_l.width() + 'px');
				_space_r.css("left", _bar_h.width() - _space_r.width() + "px");
				break;
			case "barleftright":
				_space_l.css("left", "0px");
				_track_h.css('width', hsize - _arrow_l.width() - _space_l.width() - _space_r.width() - _arrow_r.width() + 'px').css('left', _space_l.width() + 'px');
				_space_r.css("left", _bar_h.width() - _arrow_l.width() - _arrow_r.width() - _space_r.width() + "px");
				_arrow_l.css('left', _bar_h.width() - _arrow_l.width() - _arrow_r.width() + 'px');
				_arrow_r.css('left', _bar_h.width() - _arrow_r.width() + 'px');
				break;
			default:
				_arrow_l.css('left', '0px');
				_space_l.css("left", _arrow_l.width() + "px");
				_track_h.css('width', hsize - _arrow_l.width() - _space_l.width() - _space_r.width() - _arrow_r.width() + 'px').css('left', _arrow_l.width() + _space_l.width() + 'px');
				_space_r.css("left", _bar_h.width() - _arrow_r.width() - _space_r.width() + "px");
				_arrow_r.css('left', _bar_h.width() - _arrow_r.width() + 'px');
		}
		_resize.css('left', ((_vert == 1) ? hsize : 0) + hpadd + 'px').css('top', ((_horz == 1) ? vsize : 0) + vpadd + 'px');
		if (_bar_v.is(':visible') && _bar_h.is(':visible'))
		{
			if (_options.resizable)
			{
				_resize.addClass(((_horz == 1) ? 'bottom' : 'top') + ((_vert == 1) ? 'right' : 'left'));
			}
			else
			{
				_resize.addClass('disabled');
			}
			_resize.show();
		}
		else
		{
			_resize.hide();
		}
		_container.css('margin-left', ((_vert == 1) ? 0 : _bar_v.width()) + 'px').css('margin-top', ((_horz == 1) ? 0 : _bar_h.height()) + 'px');
		$(theObj).data('width' + _namespace, $(theObj).width());
		$(theObj).data('height' + _namespace, $(theObj).height());
		$(theObj).data('scrollWidth' + _namespace, _contentWidth());
		$(theObj).data('scrollHeight' + _namespace, _contentHeight());
		$(theObj).data('paddingLeft' + _namespace, $(theObj).css("padding-left"));
		$(theObj).data('paddingTop' + _namespace, $(theObj).css("padding-top"));
	};

	// for the initial size
	_initContainer();
	
	// get the ratio, bar size vs. scroll dimension
	
	var _verticalRatio = function(){
		var _grip_h = $(theObj).data("_grip_h");
		if (_grip_h)
		{
			return (_track_v.height() - _grip_h) / (_contentHeight() - _container.height());
		}
		return Math.min(_track_v.height() / _contentHeight(), 1);
	};
	
	var _horizontalRatio = function(){
		var _grip_w = $(theObj).data("_grip_w");
		if (_grip_w)
		{
			return (_track_h.width() - _grip_w) / (_contentWidth() - _container.width());
		}
		return Math.min(_track_h.width() / _contentWidth(), 1);
	};
	
	// (re)init vertical bar
	var _initVerticals = function (){
		// check if should not be visible
		if (_container.get(0).scrollHeight <= $(theObj).height() - _bar_h.height())
		{
			_bar_v.addClass('disabled');
			_track_t.hide();
			_drag_vc.hide();
			_track_b.hide();
			return;
		}
		_bar_v.removeClass('disabled');
		var ratio = _verticalRatio();
		var top = $(_container).scrollTop() * ratio;
		var _grip_h = $(theObj).data("_grip_h");
		var min = _drag_t.height() + _grip_h + _drag_b.height();
		var size = _grip_h ? min : Math.max(Math.min(Math.round(_bar_v.height() * ratio), _track_v.height()), min);
		if (top + size > _track_v.height())
		{
			top = _track_v.height() - size;
		}
		if (top > 0)
		{
			_track_t.css('height', top + 'px').show();
		}
		else
		{
			_track_t.hide();
		}
		if (size > 0)
		{
			_drag_vc.css('height', size + 'px').css('top', top + 'px').show();
			if (size > _drag_t.height() + _drag_b.height())
			{
				_drag_v.css('height', size - min + 'px').css('top', _drag_t.height() + 'px').show();
				if ((_drag_vg.height() <= size - min) || _grip_h)
				{
					_drag_vg.css('top', Math.round(size / 2 - _drag_vg.height() / 2) - _drag_t.height() + 'px').show();
				}
				else
				{
					_drag_vg.hide();
				}
			}
			else
			{
				_drag_v.hide();
			}
			_drag_b.css('top', size - _drag_b.height() + 'px');
		}
		else
		{
			_drag_vc.hide();
		}
		if (top + size < _track_v.height())
		{
			_track_b.css('height', _track_v.height() - (top + size)).css('top', top + size + 'px').show();
		}
		else
		{
			_track_b.hide();
		}
	};
	
	// (re)init horizontal bar
	var _initHorizontals = function (){
		// check if should not be visible
		if (_container.get(0).scrollWidth <= $(theObj).width() - _bar_v.width())
		{
			_bar_h.addClass('disabled');
			_track_l.hide();
			_drag_hc.hide();
			_track_r.hide();
			return;
		}
		_bar_h.removeClass('disabled');
		var ratio = _horizontalRatio();
		var left = $(_container).scrollLeft() * ratio;
		var _grip_w = $(theObj).data("_grip_w");
		var min = _drag_l.width() + _grip_w + _drag_r.width();
		var size = _grip_w ? min : Math.max(Math.min(Math.round(_bar_h.width() * ratio), _track_h.width()), min);
		if (left + size > _track_h.width())
		{
			left = _track_h.width() - size;
		}
		if (left > 0)
		{
			_track_l.css('width', left + 'px').show();
		}
		else
		{
			_track_l.hide();
		}
		if (size > 0)
		{
			_drag_hc.css('width', left + 'px').css('left', left + 'px').show();
			if (size > _drag_l.width() + _drag_r.width())
			{
				_drag_h.css('width', size - min + 'px').css('left', _drag_l.width() + 'px').show();
				if ((_drag_hg.width() <= size - min) || _grip_w)
				{
					_drag_hg.css('left', Math.round(size / 2 - _drag_hg.width() / 2) - _drag_l.width() + 'px').show();
				}
				else
				{
					_drag_hg.hide();
				}
			}
			else
			{
				_drag_h.hide();
			}
			_drag_r.css('left', size - _drag_r.width() + 'px');
		}
		else
		{
			_drag_hc.hide();
		}
		if (left + size < _track_h.width())
		{
			_track_r.css('width', _track_h.width() - (left + size)).css('left', left + size + 'px').show();
		}
		else
		{
			_track_r.hide();
		}
	};
	
	// for the initial position
	_initVerticals();
	_initHorizontals();
	
	// scroll vertically
	var _scrollVertically = function(delta){
		if (_contentHeight() > $(theObj).height() - _bar_h.height())
		{
			var pos, timed;
			if (typeof(delta) == 'object')
			{
				pos = Math.max($(_container).scrollTop() + -delta.delta * _options.delta, 0);
				timed = delta.timed;
			}
			else
			{
				pos = delta;
				timed = _options.lineTimer;
			}
			if (_options.smoothScroll)
			{
				$(_container).stop(false, true).animate({'scrollTop':pos}, {
					duration:timed,
					easing:'linear',
					complete:function(){
						$(theObj).trigger('scroll');
						_initVerticals();
					},
					step:function(){
						_initVerticals();
					},
					queue:true
				});
			}
			else
			{
				_container.get(0).scrollTop = pos;
			}
		}
		else
		{
			_container.get(0).scrollTop = 0;
		}
		$(theObj).trigger('scroll');
		_initVerticals();
	};

	// scroll horizontally
	var _scrollHorizontally = function(delta){
		if (_contentWidth() > $(theObj).width() - _bar_v.width())
		{
			var pos, timed;
			if (typeof(delta) == 'object')
			{
				pos = Math.max($(_container).scrollLeft() + -delta.delta * _options.delta, 0);
				timed = delta.timed;
			}			
			else
			{
				pos = delta;
				timed = _options.lineTimer;
			}			
			if (_options.smoothScroll)
			{
				$(_container).stop(false, true).animate({'scrollLeft':pos}, {
					duration:timed,
					easing:'linear',
					complete:function(){
						$(theObj).trigger('scroll');
						_initHorizontals();
					},
					step:function(){
						_initHorizontals();
					},
					queue:true
				});
			}
			else
			{
				_container.get(0).scrollLeft = pos;
			}
		}
		else
		{
			_container.get(0).scrollLeft = 0;
		}
		$(theObj).trigger('scroll');
		_initHorizontals();
	};
	
	// bind mouse wheel on content
	if (_options.bindMouse)
	{
		$(theObj).bind('mousewheel' + _namespace, function(e, delta){
			if (typeof(delta) == 'object')
			{
				_scrollVertically(delta);
			}
			else
			{
				_scrollVertically({'delta':delta*2,'timed':_options.lineTimer});
			}
			return false;
		});
	}
	
	// vertical scollbar	
	_bar_v.bind('mousewheel' + _namespace, function(e, delta){
		if (typeof(delta) == 'object')
		{
  	  _scrollVertically(delta);
		}
		else
		{
			_scrollVertically({'delta':delta*2,'timed':_options.lineTimer});
		}
		return false;
	}).bind('selectstart' + _namespace, function(){
		return false;																	
	}).bind('mousedown' + _namespace, function(){
		$(theObj).focus();
		return false;
	}).bind('mouseup' + _namespace, function(){
		return false;
	}).bind('click' + _namespace, function(){
		return false;
	});
	
	// horizontal scollbar
	_bar_h.bind('mousewheel' + _namespace, function(e, delta){
		if (typeof(delta) == 'object')
		{
		  _scrollHorizontally(delta);
		}
		else
		{
			_scrollHorizontally({'delta':delta*2,'timed':_options.lineTimer});
		}
		return false;
	}).bind('selectstart' + _namespace, function(){
		return false;																	
	}).bind('mousedown' + _namespace, function(){
		$(theObj).focus();
		return false;
	}).bind('mouseup' + _namespace, function(){
		return false;
	}).bind('click' + _namespace, function(){
		return false;
	});
	
	// keep current mouse coords (with the start value from a click for example)
	var _coords = {'curr':{'x':null, 'y':null}, 'start':{'x':null, 'y':null}, 'ref':{'x':null, 'y':null}};
	
	// keep starting values
	var _resizeStart = function(){
		_coords.start.x = _coords.curr.x;
		_coords.start.y = _coords.curr.y;
		_coords.ref.x = $(theObj).width();
		_coords.ref.y = $(theObj).height();
	};

	// called on mousemove (when in resize)
	var _resizeMove = function(){
		if (_resize.get(0) == _lastSelected)
		{
			var width = Math.max(_coords.ref.x + _coords.curr.x - _coords.start.x, _resize.width() * 4);
			var height = Math.max(_coords.ref.y + _coords.curr.y - _coords.start.y, _resize.height() * 4);
			$(theObj).trigger('onresize', {'width':width, 'height':height});
		}
	};

	// bind events on the resizer
	_resize.bind('selectstart' + _namespace, function(){
		return false;																	
	}).bind('mousedown' + _namespace, function(){
		$(theObj).focus();
		_lastSelected = this;
		_delayFinish();
		_resizeStart();
		return false;
	}).bind('mouseup' + _namespace, function(){
		_unselect();
		return false;
	}).bind('click' + _namespace, function(){
		_unselect();
		return false;
	});	
	
	// keep current selected element (arrows, track, grip etc.)
	var _lastSelected = null;
	
  var _unselect = function (){
		$(_lastSelected).removeClass("selected");
		_lastSelected = null;
		_delayFinish();
	};

	// used for event delay
	var _delayTimer = null;
	
	// finish current operation
	var _delayFinish = function(){
		if (_delayTimer)
		{
			window.clearInterval(_delayTimer);
			_delayTimer = null;
		}
	};
	
	// execute operation with a delay
	var _delayExec = function(obj, delta, timed)
	{
		_delayFinish();
		_delayTimer = window.setInterval(function(){ obj.trigger('mousewheel', {'delta':delta, 'timed':timed}); }, timed);
	};
	
	// start a delay operation
	var _delayStart = function (obj, delta, timed, pause)
	{
		_delayFinish();
		_delayTimer = window.setInterval(function(){ _delayExec(obj, delta, timed); }, pause);
	};
	
	// handle hover event
	var _hover = function(obj, hover){
		if (hover)
		{
		  $(obj).addClass('hover');
			if (_lastSelected == obj)
			{
				$(obj).addClass('selected');
			}
			// add ehover class for the parent bar
			var parent = $(obj).parent();
			if (parent.hasClass("aciSb_bar_v") || parent.hasClass("aciSb_bar_h"))
			{
				parent.addClass('ehover');
			}
			else
			{
				parent = parent.parent();
				parent.addClass('ehover');
			}			
		}
		else
		{
			$(obj).removeClass('hover').removeClass('selected');
			// remove ehover class for the parent bar
			var parent = $(obj).parent();
			if (parent.hasClass("aciSb_bar_v") || parent.hasClass("aciSb_bar_h"))
			{
				parent.removeClass('ehover');
			}
			else
			{
				parent = parent.parent();
				parent.removeClass('ehover');
			}
		}
	};
	
	// register arrow events
	var _initArrow = function(obj, delta){
		obj.bind('mouseover' + _namespace, function(){
			_hover(this, true);
		}).bind('mousemove' + _namespace, function(){
			_hover(this, true);
		}).bind('mouseout' + _namespace, function(){
			_delayFinish();
			_hover(this, false);
		}).bind('mousedown' + _namespace, function(){
			_lastSelected = this;
			$(this).trigger('mousewheel', {'delta':delta,'timer':_options.lineTimer});
			_delayStart($(this), delta, _options.lineTimer, _options.lineDelay);
			$(this).addClass('selected');
		}).bind('mouseup' + _namespace, function(){
			_unselect();
		}).bind('click' + _namespace, function(){
			_unselect();
			return false;
		});
	};
	
	// bind arrow events for all bars
	_initArrow(_arrow_t, 1);
	_initArrow(_arrow_b, -1);
	_initArrow(_arrow_l, 1);
	_initArrow(_arrow_r, -1);
	
	// register track events
	var _initTrack = function(obj, delta)
	{
		obj.bind('mouseover' + _namespace, function(){
			_hover(this, true);
		}).bind('mousemove' + _namespace, function(){
			_hover(this, true);
		}).bind('mouseout' + _namespace, function(){
			_delayFinish();
			_hover(this, false);
		}).bind('mousedown' + _namespace, function(){
			_lastSelected = this;
			$(this).trigger('mousewheel', {'delta':delta * ($(theObj).height() / (_options.delta * 2)),'timer':_options.lineTimer});
			_delayStart($(this).parent().parent(), delta * ($(theObj).height() / _options.delta), _options.pageTimer, _options.pageDelay);
			$(this).addClass('selected');
		}).bind('mouseup' + _namespace, function(){
			_unselect();
		}).bind('click' + _namespace, function(){
			_unselect();
			return false;
		})
	};
	
	// bind track events for all bars
	_initTrack(_track_t, 1);
	_initTrack(_track_b, -1);
	_initTrack(_track_l, 1);
	_initTrack(_track_r, -1);
	
	// register space events
	var _initSpace = function(obj)
	{
		obj.bind('mouseover' + _namespace, function(){
			_hover(this, true);
		}).bind('mousemove' + _namespace, function(){
			_hover(this, true);
		}).bind('mouseout' + _namespace, function(){
			_delayFinish();
			_hover(this, false);
		}).bind('mouseup' + _namespace, function(){
			_unselect();
		}).bind('click' + _namespace, function(){
			_unselect();
			return false;
		})
	};
	
	// bind space events for all bars
	_initSpace(_space_t);
	_initSpace(_space_b);
	_initSpace(_space_l);
	_initSpace(_space_r);	
	
	// keep starting values
	var _gripStart = function(){
		_coords.start.x = _coords.curr.x;
		_coords.start.y = _coords.curr.y;
		_coords.ref.x = $(_container).scrollLeft();
		_coords.ref.y = $(_container).scrollTop();
	};
	
	// called when in scroll (with the mouse)
	var _gripScroll = function(){
		// check if it's the vertical bar
		if (_drag_vc.get(0) == _lastSelected)
		{
			_bar_v.addClass("ehover");
			_drag_vc.addClass("selected");
			var ref = _coords.ref.y;
			var diff =  _coords.curr.y - _coords.start.y;
			var ratio = _verticalRatio();
			var top = (Math.abs(_coords.ref.y * ratio) + diff) / ratio;
			_scrollVertically(top);
		}
		// check if it's the horizontal bar
		if (_drag_hc.get(0) == _lastSelected)
		{
			_bar_h.addClass("ehover");
			_drag_hc.addClass("selected");
			var ref = _coords.ref.x;
			var diff =  _coords.curr.x - _coords.start.x;
			var ratio = _horizontalRatio();
			var left = (Math.abs(_coords.ref.x * ratio) + diff) / ratio;
			_scrollHorizontally(left);
		}
	};
	
	// called after the scroll
	var _gripEnd = function(){
		_bar_v.removeClass("ehover");
		_drag_vc.removeClass("selected");		
		_bar_h.removeClass("ehover");
		_drag_hc.removeClass("selected");			
	};

	// register grip events
	var _initGrip = function(obj){
		obj.bind('mouseover' + _namespace, function(){
			_hover(this, true);
		}).bind('mousemove' + _namespace, function(){
			_hover(this, true);
		}).bind('mouseout' + _namespace, function(){
			_delayFinish();
			_hover(this, false);
		}).bind('mousedown' + _namespace, function(){
			_lastSelected = this;
			_delayFinish();
			_gripStart();
			$(this).addClass('selected');
		}).bind('mouseup' + _namespace, function(){
			_unselect();
		}).bind('click' + _namespace, function(){
			_unselect();
			return false;
		});
	};
	
	// bind grip events for all bars
	_initGrip(_drag_vc);
	_initGrip(_drag_hc);
	
	// keep focus state
	var _focus = false;
	
	if (_options.bindKeyboard)
	{
		// keyboard handling
		$(theObj).bind('keydown' + _namespace, function(e){
			if (!_focus)
			{
				// do not handle if we do not have focus
				return;
			}
			switch (e.which)
			{
				case 38: // up
					_arrow_t.trigger('mousedown').trigger('mouseup');
					return false;
				case 40: // down
					_arrow_b.trigger('mousedown').trigger('mouseup');
					return false;
				case 37: // left
					_arrow_l.trigger('mousedown').trigger('mouseup');
					return false;
				case 39: // right
					_arrow_r.trigger('mousedown').trigger('mouseup');
					return false;
				case 33: // pgup
					_track_t.trigger('mousedown').trigger('mouseup');
					return false;
				case 34: // pgdown
					_track_b.trigger('mousedown').trigger('mouseup');
					return false;
				case 36: // home
					_scrollVertically(0);
					_scrollHorizontally(0);
					return false;	
				case 35: // end
					_scrollVertically(_contentHeight());
					_scrollHorizontally(0);
					return false;	
			}
		});
	}
	
	// just make sure we are done with the mouse
        $('html').bind('mouseup' + _namespace + '-' + _index, function(){
		_unselect();
		//_gripEnd();
	}).bind('mousemove' + _namespace + '-' + _index, function(e){
		_coords.curr.x = e.pageX;
		_coords.curr.y = e.pageY;
		if (_lastSelected)
		{
			_gripScroll();
			_resizeMove();
		}
           });
	/*$('html').bind('mouseup' + _namespace + '-' + _index, function(){
		_unselect();
		_gripEnd();
	}).bind('mousemove' + _namespace + '-' + _index, function(e){
		_coords.curr.x = e.pageX;
		_coords.curr.y = e.pageY;
		if (_lastSelected)
		{
			_gripScroll();
			_resizeMove();
		}
	}).bind('mouseout' + _namespace + '-' + _index, function(e){
		if (!e.relatedTarget)
		{
			_unselect();
			_gripEnd();
		}
	});*/
	
	// get contained element position
	var _elementPos = function(obj){
		var pos = obj.position();
		var top = $(_container).scrollTop() + pos.top;
		var left = $(_container).scrollLeft() + pos.left;
		return {'top':top, 'left':left};
	};
	
	// keep timeout reference
	var _change = null;
	
	// bind event handlers to respond to
	$(theObj).bind('focus' + _namespace, function(){
		_focus = true;
	}).bind('blur' + _namespace, function(){
		_focus = false;
	}).bind('scrollup' + _namespace, function(){
		_arrow_t.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('pageup' + _namespace, function(){
		_track_t.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('scrolldown' + _namespace, function(){
		_arrow_b.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('pagedown' + _namespace, function(){
		_track_b.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('scrollleft' + _namespace, function(){
		_arrow_l.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('pageleft' + _namespace, function(){
		_track_l.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('scrollright' + _namespace, function(){
		_arrow_r.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('pageright' + _namespace, function(){
		_track_r.trigger('mousedown').trigger('mouseup');
		return false;
	}).bind('scrollto' + _namespace, function(e, data){
		// scroll to top/left position (with animation)
		if (typeof(data) != 'object')
		{
			return false;
		}
		if (typeof(data.top) != 'undefined')
		{
			var top = data.top;
			if (typeof(top) == 'string')
			{
				var ret = null;
				var rex = new RegExp('^([0-9]+)%$');
				if (ret = rex.exec(top))
				{
					top = Math.round((_contentHeight() - $(theObj).height() + _bar_h.height()) * parseFloat(ret[1]) / 100);
				}
				else	
				{
					rex = new RegExp('^([0-9]+)$');
					if (ret = rex.exec(top))
					{
						top = Math.abs(parseInt(ret[1]));
					}
				}
			}
			if (data.animate)
			{
				$(_container).animate({'scrollTop': top}, {
					duration: data.duration,
					easing: data.animate,
					complete: function(){
						$(theObj).trigger("scroll");
						_initVerticals();
					},
					step: function(){
						_initVerticals();
					} 
				});
			}
			else
			{
				_scrollVertically(top);
			}
		}
		if (typeof(data.left) != 'undefined')
		{
			var left = data.left;
			if (typeof(left) == 'string')
			{
				var ret = null;
				var rex = new RegExp('^([0-9]+)%$');
				if (ret = rex.exec(left))
				{
					left = Math.round((_contentWidth() - $(theObj).width() + _bar_v.width()) * parseFloat(ret[1]) / 100);
				}
				else	
				{
					rex = new RegExp('^([0-9]+)$');
					if (ret = rex.exec(left))
					{
						left = Math.abs(parseInt(ret[1]));
					}
				}
			}
			if (data.animate)
			{
				$(_container).animate({'scrollLeft': left}, {
					duration: data.duration,
					easing: data.animate,
					complete: function(){
						$(theObj).trigger("scroll");
						_initHorizontals();
					},
					step: function(){
						_initHorizontals();
					}
				});
			}
			else
			{
				_scrollHorizontally(left);
			}
		}
		return false;
	}).bind('goto' + _namespace, function(e, data){
		// scroll to an element inside the content
		if ((typeof(data) != 'object') || (typeof(data.element) == 'undefined'))
		{
			return false;
		}
		var obj = $(data.element);
		if (obj.get(0) && $(theObj).has(obj.get(0)))
		{
			var pos = _elementPos(obj);
			var center = ((typeof(data.center) != 'boolean') ? true : data.center);
			if (center)
			{
				if (obj.width() < $(theObj).width() - _bar_v.width())
				{
					pos.left -= Math.round($(theObj).width() / 2 - obj.width() / 2);
				}
				if (obj.height() < $(theObj).height() - _bar_h.height())
				{
					pos.top -= Math.round($(theObj).height() / 2 - obj.height() / 2);
				}
			}
			var offsety = (data.offsety ? parseInt(data.offsety) : 0);
			if (Math.abs($(_container).scrollTop() - Math.abs(pos.top)) >= offsety)
			{
				if (data.animate)
				{
					$(_container).animate({'scrollTop': pos.top}, {
						duration: data.duration,
						easing: data.animate,
						complete: function(){
							$(theObj).trigger("scroll");
							_initVerticals();
						},
						step: function(){
						  _initVerticals();
						} 
					});
				}
				else					
				{
					_scrollVertically(pos.top);
				}
			}
			var offsetx = (data.offsetx ? parseInt(data.offsetx) : 0);
			if (Math.abs($(_container).scrollLeft() - Math.abs(pos.left)) >= offsetx)
			{
				if (data.animate)
				{
					$(_container).animate({'scrollLeft': pos.left}, {
						duration: data.duration,
						easing: data.animate,
						complete: function(){ 
  						$(theObj).trigger("scroll");
              _initHorizontals();
						},
						step: function(){
							_initHorizontals();
						} 
					});
				}
				else
				{
					_scrollHorizontally(pos.left);
				}
			}
		}
		return false;
	}).bind('resize' + _namespace, function(e, data){
		var sized = ($(theObj).data('width' + _namespace) != $(theObj).width()) || ($(theObj).data('height' + _namespace) != $(theObj).height());
		var width = $(theObj).data('scrollWidth' + _namespace);
		var height = $(theObj).data('scrollHeight' + _namespace);
		if (sized || (width != _contentWidth()) || (height != _contentHeight()) ||
		($(theObj).data('paddingLeft' + _namespace) != $(theObj).css("padding-left")) || ($(theObj).data('paddingTop' + _namespace) != $(theObj).css("padding-top")) || (data && data.forced))
		{
		  var top = $(_container).scrollTop();
		  var left = $(_container).scrollLeft();
			_initContainer();
			// check if we should reposition to keep in view
			if (sized && ((_contentHeight() != height) || (_contentWidth() != width)))
			{
				_container.get(0).scrollTop = Math.round(_contentHeight() * top / height);
				_container.get(0).scrollLeft = Math.round(_contentWidth() * left / width);
				$(theObj).trigger("scroll");
			}
		}
		_initVerticals();
		_initHorizontals();
		return false;
	}).bind("change" + _namespace, function(e, data){
		$(theObj).trigger("resize");
		clearTimeout(_change);
		_container.find("img").unbind(_namespace).each(function(){
			$(this).bind("load" + _namespace, function(){
				clearTimeout(_change);
				setTimeout(function(){ $(theObj).trigger("resize"); }, 200);
				$(this).unbind(_namespace);
			});
		});
		return false;
	});

  // set initial position
  $(theObj).trigger("scrollto", { top: Math.round(_contentHeight() * _scroll.top / _scroll.height), left: Math.round(_contentWidth() * _scroll.left / _scroll.width) });

	// trigger ready event
	$(theObj).trigger('ready');

}; // end _customUi

// init the control
return _initUi();

};

// unbind all events
$(window).bind('unload' + _namespace, function(){
	$('*').unbind(_namespace);
	for (var i = 1; i <= $.aciScrollBar.index; i++)
	{
		$('*').unbind(_namespace + '-' + i);
	}
});

})(jQuery);

