/*!
 * Cloudgamer JavaScript Library v0.1
 * Copyright (c) 2009 cloudgamer
 * Blog: http://cloudgamer.cnblogs.com/
 * Date: 2009-10-15
 */

var $$, $$B, $$A, $$F, $$D, $$E, $$CE, $$S;

(function(undefined){

var O, B, A, F, D, E, CE, S;


/*Object*/

O = function (id) {
	return "string" == typeof id ? document.getElementById(id) : id;
};

O.emptyFunction = function(){};

O.extend = function (destination, source, override) {
	if (override === undefined) override = true;
	for (var property in source) {
		if (override || !(property in destination)) {
			destination[property] = source[property];
		}
	}
	return destination;
};

O.deepextend = function (destination, source) {
	for (var property in source) {
		var copy = source[property];
		if ( destination === copy ) continue;
		if ( typeof copy === "object" ){
			destination[property] = arguments.callee( destination[property] || {}, copy );
		}else{
			destination[property] = copy;
		}
	}
	return destination;
};

/*from youa*/
O.wrapper = function(me, parent) {
    var ins = function() { me.apply(this, arguments); };
    var subclass = function() {};
    subclass.prototype = parent.prototype;
    ins.prototype = new subclass;
    return ins;
};


/*Browser*/

/*from youa*/
B = (function(ua){
	var b = {
		msie: /msie/.test(ua) && !/opera/.test(ua),
		opera: /opera/.test(ua),
		safari: /webkit/.test(ua) && !/chrome/.test(ua),
		firefox: /firefox/.test(ua),
		chrome: /chrome/.test(ua)
	};
	var vMark = "";
	for (var i in b) {
		if (b[i]) { vMark = "safari" == i ? "version" : i; break; }
	}
	b.version = vMark && RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0";
	
	b.ie = b.msie;
	b.ie6 = b.msie && parseInt(b.version, 10) == 6;
	b.ie7 = b.msie && parseInt(b.version, 10) == 7;
	b.ie8 = b.msie && parseInt(b.version, 10) == 8;
	
	return b;
})(window.navigator.userAgent.toLowerCase());


/*Array*/

A = function(){
	
	var ret = {
		isArray: function( obj ) {
			return Object.prototype.toString.call(obj) === "[object Array]";
		},
		indexOf: function( array, elt, from ){
			if (array.indexOf) {
				return isNaN(from) ? array.indexOf(elt) : array.indexOf(elt, from);
			} else {
				var len = array.length;
				from = isNaN(from) ? 0
					: from < 0 ? Math.ceil(from) + len : Math.floor(from);
				
				for ( ; from < len; from++ ) { if ( array[from] === elt ) return from; }
				return -1;
			}
		},
		lastIndexOf: function( array, elt, from ){
			if (array.lastIndexOf) {
				return isNaN(from) ? array.lastIndexOf(elt) : array.lastIndexOf(elt, from);
			} else {
				var len = array.length;
				from = isNaN(from) || from >= len - 1 ? len - 1
					: from < 0 ? Math.ceil(from) + len : Math.floor(from);
				
				for ( ; from > -1; from-- ) { if ( array[from] === elt ) return from; }
				return -1;
			}
		}
	};
	
	function each( object, callback ) {
		if ( undefined === object.length ){
			for ( var name in object ) {
				if (false === callback( object[name], name, object )) break;
			}
		} else {
			for ( var i = 0, len = object.length; i < len; i++ ) {
				if (i in object) { if (false === callback( object[i], i, object )) break; }
			}
		}
	};
	
	each({
			forEach: function( object, callback, thisp ){
				each( object, function(){ callback.apply(thisp, arguments); } );
			},
			map: function( object, callback, thisp ){
				var ret = [];
				each( object, function(){ ret.push(callback.apply(thisp, arguments)); });
				return ret;
			},
			filter: function( object, callback, thisp ){
				var ret = [];
				each( object, function(item){
						callback.apply(thisp, arguments) && ret.push(item);
					});
				return ret;
			},
			every: function( object, callback, thisp ){
				var ret = true;
				each( object, function(){
						if ( !callback.apply(thisp, arguments) ){ ret = false; return false; };
					});
				return ret;
			},
			some: function( object, callback, thisp ){
				var ret = false;
				each( object, function(){
						if ( callback.apply(thisp, arguments) ){ ret = true; return false; };
					});
				return ret;
			}
		}, function(method, name){
			ret[name] = function( object, callback, thisp ){
				if (object[name]) {
					return object[name]( callback, thisp );
				} else {
					return method( object, callback, thisp );
				}
			}
		});
	
	return ret;
}();


/*Function*/

F = (function(){
	var slice = Array.prototype.slice;
	return {
		bind: function( fun, thisp ) {
			var args = slice.call(arguments, 2);
			return function() {
				return fun.apply(thisp, args.concat(slice.call(arguments)));
			}
		},
		bindAsEventListener: function( fun, thisp ) {
			var args = slice.call(arguments, 2);
			return function(event) {
				return fun.apply(thisp, [E.fixEvent(event)].concat(args));
			}
		}
	};
})();


/*Dom*/

D = {
	getScrollTop: function(node) {
		var doc = node ? node.ownerDocument : document;
		return doc.documentElement.scrollTop || doc.body.scrollTop;
	},
	getScrollLeft: function(node) {
		var doc = node ? node.ownerDocument : document;
		return doc.documentElement.scrollLeft || doc.body.scrollLeft;
	},
	contains: document.defaultView
		? function (a, b) { return !!( a.compareDocumentPosition(b) & 16 ); }
		: function (a, b) { return a != b && a.contains(b); },
	rect: function(node){
		var left = 0, top = 0, right = 0, bottom = 0;
		//ie8的getBoundingClientRect获取不准确
		if ( !node.getBoundingClientRect || B.ie8 ) {
			var n = node;
			while (n) { left += n.offsetLeft, top += n.offsetTop; n = n.offsetParent; };
			right = left + node.offsetWidth; bottom = top + node.offsetHeight;
		} else {
			var rect = node.getBoundingClientRect();
			left = right = D.getScrollLeft(node); top = bottom = D.getScrollTop(node);
			left += rect.left; right += rect.right;
			top += rect.top; bottom += rect.bottom;
		};
		return { "left": left, "top": top, "right": right, "bottom": bottom };
	},
	clientRect: function(node) {
		var rect = D.rect(node), sLeft = D.getScrollLeft(node), sTop = D.getScrollTop(node);
		rect.left -= sLeft; rect.right -= sLeft;
		rect.top -= sTop; rect.bottom -= sTop;
		return rect;
	},
	curStyle: document.defaultView
		? function (elem) { return document.defaultView.getComputedStyle(elem, null); }
		: function (elem) { return elem.currentStyle; },
	getStyle: document.defaultView
		? function (elem, name) {
			var style = document.defaultView.getComputedStyle(elem, null);
			return name in style ? style[ name ] : style.getPropertyValue( name );
		}
		: function (elem, name) {
			var style = elem.style, curStyle = elem.currentStyle;
			//透明度 from youa
			if ( name == "opacity" ) {
				if ( /alpha\(opacity=(.*)\)/i.test(curStyle.filter) ) {
					var opacity = parseFloat(RegExp.$1);
					return opacity ? opacity / 100 : 0;
				}
				return 1;
			}
			if ( name == "float" ) { name = "styleFloat"; }
			var ret = curStyle[ name ] || curStyle[ S.camelize( name ) ];
			//单位转换 from jqury
			if ( !/^-?\d+(?:px)?$/i.test( ret ) && /^\-?\d/.test( ret ) ) {
				var left = style.left, rtStyle = elem.runtimeStyle, rsLeft = rtStyle.left;
				
				rtStyle.left = curStyle.left;
				style.left = ret || 0;
				ret = style.pixelLeft + "px";
				
				style.left = left;
				rtStyle.left = rsLeft;
			}
			return ret;
		},
	setStyle: function(elems, style, value) {
		if ( !elems.length ) { elems = [ elems ]; }
		if ( typeof style == "string" ) { var s = style; style = {}; style[s] = value; }
		A.forEach( elems, function(elem ) {
			for (var name in style) {
				var value = style[name];
				if (name == "opacity" && B.ie) {
					//ie透明度设置 from jquery
					elem.style.filter = (elem.currentStyle && elem.currentStyle.filter || "").replace( /alpha\([^)]*\)/, "" ) + " alpha(opacity=" + (value * 100 | 0) + ")";
				} else if (name == "float") {
					elem.style[ B.ie ? "styleFloat" : "cssFloat" ] = value;
				} else {
					elem.style[ S.camelize( name ) ] = value;
				}
			};
		});
	},
	getSize: function(elem) {
		var width = elem.offsetWidth, height = elem.offsetHeight;
		if ( !width && !height ) {
			var repair = !D.contains( document.body, elem ), parent;
			if ( repair ) {//如果元素不在body上
				parent = elem.parentNode;
				document.body.insertBefore(elem, document.body.childNodes[0]);
			}
			var style = elem.style,
				cssShow = { position: "absolute", visibility: "hidden", display: "block", left: "-9999px", top: "-9999px" },
				cssBack = { position: style.position, visibility: style.visibility, display: style.display, left: style.left, top: style.top };
			D.setStyle( elem, cssShow );
			width = elem.offsetWidth; height = elem.offsetHeight;
			D.setStyle( elem, cssBack );
			if ( repair ) {
				parent ? parent.appendChild(elem) : document.body.removeChild(elem);
			}
		}
		return { "width": width, "height": height };
	}
};


/*Event*/
E = (function(){
	/*from dean edwards*/
	var addEvent, removeEvent, guid = 1,
		storage = function( element, type, handler ){
			if (!handler.$$guid) handler.$$guid = guid++;
			if (!element.events) element.events = {};
			var handlers = element.events[type];
			if (!handlers) {
				handlers = element.events[type] = {};
				if (element["on" + type]) {
					handlers[0] = element["on" + type];
				}
			}
		};
	if ( window.addEventListener ) {
		var fix = { "mouseenter": "mouseover", "mouseleave": "mouseout" };
		addEvent = function( element, type, handler ){
			if ( type in fix ) {
				storage( element, type, handler );
				var fixhandler = element.events[type][handler.$$guid] = function(event){
					var related = event.relatedTarget;
					if ( !related || (element != related && !(element.compareDocumentPosition(related) & 16)) ){
						handler.call(this, event);
					}
				};
				element.addEventListener(fix[type], fixhandler, false);
			} else {
				element.addEventListener(type, handler, false);
			};
		};
		removeEvent = function( element, type, handler ){
			if ( type in fix ) {
				if (element.events && element.events[type]) {
					element.removeEventListener(fix[type], element.events[type][handler.$$guid], false);
					delete element.events[type][handler.$$guid];
				}
			} else {
				element.removeEventListener(type, handler, false);
			};
		};
	} else {
		addEvent = function( element, type, handler ){
			storage( element, type, handler );
			element.events[type][handler.$$guid] = handler;
			element["on" + type] = handleEvent;
		};
		removeEvent = function( element, type, handler ){
			if (element.events && element.events[type]) {
				delete element.events[type][handler.$$guid];
			}
		};
		function handleEvent() {
			var returnValue = true, event = fixEvent();
			var handlers = this.events[event.type];
			for (var i in handlers) {
				this.$$handleEvent = handlers[i];
				if (this.$$handleEvent(event) === false) {
					returnValue = false;
				}
			}
			return returnValue;
		};
	}
	
	function fixEvent(event) {
		if (event) return event;
		event = window.event;
		event.pageX = event.clientX + D.getScrollLeft(event.srcElement);
		event.pageY = event.clientY + D.getScrollTop(event.srcElement);
		event.target = event.srcElement;
		event.stopPropagation = stopPropagation;
		event.preventDefault = preventDefault;
		var relatedTarget = {
				"mouseout": event.toElement, "mouseover": event.fromElement
			}[ event.type ];
		if ( relatedTarget ){ event.relatedTarget = relatedTarget;}
		
		return event;
	};
	function stopPropagation() { this.cancelBubble = true; };
	function preventDefault() { this.returnValue = false; };
	
	return {
		"addEvent": addEvent,
		"removeEvent": removeEvent,
		"fixEvent": fixEvent
	};
})();


/*CustomEvent*/

CE = (function(){
	var guid = 1;
	return {
		addEvent: function( object, type, handler ){
			if (!handler.$$$guid) handler.$$$guid = guid++;
			if (!object.cusevents) object.cusevents = {};
			if (!object.cusevents[type]) object.cusevents[type] = {};
			object.cusevents[type][handler.$$$guid] = handler;
		},
		removeEvent: function( object, type, handler ){
			if (object.cusevents && object.cusevents[type]) {
				delete object.cusevents[type][handler.$$$guid];
			}
		},
		fireEvent: function( object, type ){
			if (!object.cusevents) return;
			var args = Array.prototype.slice.call(arguments, 2),
				handlers = object.cusevents[type];
			for (var i in handlers) {
				handlers[i].apply(object, args);
			}
		},
		clearEvent: function( object ){
			if (!object.cusevents) return;
			for (var type in object.cusevents) {
				var handlers = object.cusevents[type];
				for (var i in handlers) {
					handlers[i] = null;
				}
				object.cusevents[type] = null;
			}
			object.cusevents = null;
		}
	};
})();


/*String*/

S = {
	camelize: function(s){
		return s.replace(/-([a-z])/ig, function(all, letter) { return letter.toUpperCase(); });
	}
};


/*System*/

// remove css image flicker
if (B.ie6) {
	try {
		document.execCommand("BackgroundImageCache", false, true);
	} catch(e) {}
};


/*define*/

$$ = O; $$B = B; $$A = A; $$F = F; $$D = D; $$E = E; $$CE = CE; $$S = S;

})();











/////////////////////////////////////////////////////////////

var SlideView = function(container, options){
	this._initialize( container, options );
	this._initContainer();
	this._initNodes();
	this.reset( this.options.defaultIndex );
};
SlideView.prototype = {
  //初始化程序
  _initialize: function(container, options) {
	
	var container = this._container = $$(container);//容器对象
	this._timerDelay = null;//延迟计时器
	this._timerMove = null;//移动计时器
	this._time = 0;//时间
	this._index = 0;//索引
	
	var opt = this._setOptions(options);
	
	this.interval = opt.interval | 0;
	this.delay = opt.delay | 0;
	this.duration = opt.duration | 0;
	this.tween = opt.tween;
	this.autoClose = !!opt.autoClose;
	this.onShow = opt.onShow;
	this.onClose = opt.onClose;
	
	//设置参数
	var pos =this._pos = /^(bottom|top|right|left)$/.test( opt.mode.toLowerCase() ) ? RegExp.$1 : "left";
	this._horizontal = /right|left/.test( this._pos );
	this._reverse = /bottom|right/.test( this._pos );
	
	//获取滑动元素
	var nodes = opt.nodes ? $$A.map( opt.nodes, function(n) { return n; } )
		: $$A.filter( container.childNodes, function(n) { return n.nodeType == 1; });
	//创建滑动对象集合
	this._nodes = $$A.map( nodes, function(node){
		var style = node.style;
		return { "node": node, "style": style[pos], "position": style.position, "zIndex": style.zIndex };
	});
	
	//设置程序
	this._MOVE = $$F.bind( this._move, this );
	
	var CLOSE = $$F.bind( this.close, this );
	this._LEAVE = $$F.bind( function(){
		clearTimeout(this._timerDelay);
		$$CE.fireEvent( this, "leave" );
		if ( this.autoClose ) { this._timerDelay = setTimeout( CLOSE, this.delay ); }
	}, this );
	
	$$CE.fireEvent( this, "init" );
  },
  //设置默认属性
  _setOptions: function(options) {
    this.options = {//默认值
		nodes:			null,//自定义展示元素集合
		mode:			"left",//方向
		max:			0,//展示尺寸(像素或百分比)
		min:			0,//收缩尺寸(像素或百分比)
		delay:			100,//触发延时
		interval:		20,//滑动间隔
		duration:		20,//滑动持续时间
		defaultIndex:	null,//默认展示索引
		autoClose:		true,//是否自动恢复
		tween:			function(t,b,c,d){ return -c * ((t=t/d-1)*t*t*t - 1) + b; },//tween算子
		onShow:			function(index){},//滑动展示时执行
		onClose:		function(){}//滑动关闭执行
    };
    return $$.extend(this.options, options || {});
  },
  //设置容器
  _initContainer: function() {
	//容器样式设置
	var container = this._container, style = container.style, position = $$D.getStyle( container, "position" );
	this._style = { "position": style.position, "overflow": style.overflow };//备份样式
	if ( position != "relative" && position != "absolute" ) { style.position = "relative"; }
	style.overflow = "hidden";
	//移出容器时
	$$E.addEvent( container, "mouseleave", this._LEAVE );
	//设置滑动元素
	var zIndex = 100, gradient = this._reverse ? -1 : 1;
	this._each( function(o){
		var style = o.node.style;
		style.position = "absolute"; style.zIndex = zIndex += gradient;
	});
	
	$$CE.fireEvent( this, "initContainer" );
  },
  //设置滑动对象
  _initNodes: function() {
	var len = this._nodes.length, maxIndex = len - 1,
		type = this._horizontal ? "Width" : "Height", offset = "offset" + type,
		clientSize = this._container[ "client" + type ],
		defaultSize = Math.round( clientSize / len ),
		//计算默认目标值的函数
		getDefaultTarget = this._reverse
			? function(i){ return defaultSize * ( maxIndex - i ); }
			: function(i){ return defaultSize * i; },
		max = this.options.max, min = this.options.min, getMax, getMin;
	//设置参数函数
	if ( max > 0 || min > 0 ) {//自定义参数值
		//小数按百分比设置
		if ( max > 0  ) {
			max = Math.max( max <= 1 ? max * clientSize : Math.min( max, clientSize ), defaultSize );
			min = ( clientSize - max ) / maxIndex;
		} else {
			min = Math.min( min < 1 ? min * clientSize : min, defaultSize );
			max = clientSize - maxIndex * min;
		}
		getMax = function(){ return max; };
		getMin = function(){ return min; };
	} else {//根据元素尺寸设置参数值
		getMax = function(o){ return Math.max( Math.min( o.node[ offset ], clientSize ), defaultSize ); };
		getMin = function(o){ return ( clientSize - o.max ) / maxIndex; };
	}
	
	//设置滑动对象
	this._each( function(o, i){
		//移入滑动元素时执行程序
		var node = o.node, SHOW = $$F.bind( this.show, this, i );
		o.SHOW = $$F.bind( function(){
			clearTimeout(this._timerDelay);
			this._timerDelay = setTimeout( SHOW, this.delay );
			$$CE.fireEvent( this, "enter", i );
		}, this );
		$$E.addEvent( node, "mouseenter", o.SHOW );
		//计算尺寸
		o.current = o.defaultTarget = getDefaultTarget(i);//默认目标值
		o.max = getMax(o); o.min = getMin(o);
	});
	
	$$CE.fireEvent( this, "initNodes" );
  },
  
  //根据索引滑动展示
  show: function(index) {
	this._setMove( index | 0 );
	this.onShow( this._index );
	this._easeMove();
  },
  //滑动到默认状态
  close: function() {
	this._setMove();
	this.onClose();
	this._easeMove();
  },
  //重置为默认状态或展开索引对应滑动对象
  reset: function(index) {
	clearTimeout(this._timerDelay);
	if ( index == undefined ) {
		this._defaultMove();
	} else {
		this._setMove(index);
		this.onShow( this._index );
		this._targetMove();
	}
  },
  
  //设置滑动参数
  _setMove: function(index) {
	var setTarget;//设置目标值函数
	if ( index == undefined ) {//设置默认状态目标值
		getTarget = function(o){ return o.defaultTarget; }
	} else {//根据索引设置滑动目标值
		var nodes = this._nodes, maxIndex = nodes.length - 1;
		//设置索引
		this._index = index = index < 0 || index > maxIndex ? 0 : index | 0;
		//设置展示参数
		var nodeShow = nodes[ index ], min = nodeShow.min, max = nodeShow.max;
		getTarget = function(o, i){ return i <= index ? min * i : min * ( i - 1 ) + max; };
		if ( this._reverse ) {
			var get = getTarget;
			index = maxIndex - index;
			getTarget = function(o, i){ return get( o, maxIndex - i ); }
		}
	}
	this._each( function(o, i){
		o.target = getTarget(o, i);//设置目标值
		o.begin = o.current;//设置开始值
		o.change = o.target - o.begin;//设置变化值
	});
	$$CE.fireEvent( this, "setMove", index );
  },
  
  //滑移程序
  _easeMove: function() {
	this._time = 0; this._move();
  },
  //移动程序
  _move: function() {
	if ( this._time < this.duration ){//未到达
		this._tweenMove();
		this._time++;
		this._timerMove = setTimeout( this._MOVE, this.interval );
	} else {//完成
		this._targetMove();//防止计算误差
		$$CE.fireEvent( this, "finish" );
	}
  },
  
  //tween移动函数
  _tweenMove: function() {
	this._setPos( function(o) {
		return this.tween( this._time, o.begin, o.change, this.duration );
	});
	$$CE.fireEvent( this, "tweenMove" );
  },
  //目标值移动函数
  _targetMove: function() {
	this._setPos( function(o) { return o.target; } );
	$$CE.fireEvent( this, "targetMove" );
  },
  //默认值移动函数
  _defaultMove: function() {
	this._setPos( function(o) { return o.defaultTarget; } );
	$$CE.fireEvent( this, "defaultMove" );
  },
  //设置坐标值
  _setPos: function(method) {
	clearTimeout(this._timerMove);
	var pos = this._pos;
	this._each( function(o, i) {
		o.node.style[ pos ] = (o.current = Math.round(method.call( this, o ))) + "px";
	});
  },
  
  //历遍滑动对象集合
  _each: function(callback) {
	$$A.forEach( this._nodes, callback, this );
  },
  
  //销毁程序
  dispose: function() {
	clearTimeout(this._timerDelay);
	clearTimeout(this._timerMove);
	
	$$CE.fireEvent( this, "dispose" );
	
	var pos = this._pos;
	this._each( function(o) {
		var style = o.node.style;
		style[pos] = o.style; style.zIndex = o.zIndex; style.position = o.position;//恢复样式
		$$E.removeEvent( o.node, "mouseenter", o.SHOW ); o.SHOW = o.node = null;
	});
	$$E.removeEvent( this._container, "mouseleave", this._LEAVE );
	
	$$D.setStyle( this._container, this._style );
	
	this._container = this._nodes = this._MOVE = this._LEAVE = null;
	$$CE.clearEvent( this );
  }
};


//自动展示扩展
SlideView.prototype._initialize = (function(){
	var init = SlideView.prototype._initialize,
		reset = SlideView.prototype.reset,
		methods = {
			"init": function(){
				this.autoDelay = this.options.autoDelay | 0;
				
				this._autoTimer = null;//定时器
				this._autoPause = false;//暂停自动展示
				//展示下一个滑动对象
				this._NEXT = $$F.bind( function(){ this.show( this._index + 1 ); }, this );
			},
			"leave": function(){
				this.autoClose = this._autoPause = false;
				this._autoNext();
			},
			"enter": function(){
				clearTimeout(this._autoTimer);
				this._autoPause = true;
			},
			"finish": function(){
				this._autoNext();
			},
			"dispose": function(){
				clearTimeout(this._autoTimer);
			}
		},
		prototype = {
			_autoNext: function(){
				if ( !this._autoPause ) {
					clearTimeout(this._autoTimer);
					this._autoTimer = setTimeout( this._NEXT, this.autoDelay );
				}
			},
			reset: function(index) {
				reset.call( this, index == undefined ? this._index : index );
				this._autoNext();
			}
		};
	return function(){
		var options = arguments[1];
		if ( options && options.auto ) {
			//扩展options
			$$.extend( options, {
				autoDelay:	5000//展示时间
			}, false );
			//扩展属性
			$$.extend( this, prototype );
			//扩展钩子
			$$A.forEach( methods, function( method, name ){
				$$CE.addEvent( this, name, method );
			}, this );
		}
		init.apply( this, arguments );
	}
})();


//提示信息扩展
SlideView.prototype._initialize = (function(){
	var init = SlideView.prototype._initialize,
		methods = {
			"init": function(){
				//坐标样式
				this._tipPos = /^(bottom|top|right|left)$/.test( this.options.tipPos.toLowerCase() ) ? RegExp.$1 : "bottom";
			},
			"initNodes": function(){
				var opt = this.options, tipTag = opt.tipTag, tipClass = opt.tipClass,
					re = tipClass && new RegExp("(^|\\s)" + tipClass + "(\\s|$)"),
					getTipNode =  function(node){
						var nodes = node.getElementsByTagName( tipTag );
						if ( tipClass ) {
							nodes = $$A.filter( nodes, function(n){ return re.test(n.className); } );
						}
						return nodes[0];
					};
				//设置提示对象
				var tipShow = opt.tipShow, tipClose = opt.tipClose,
					offset = /right|left/.test( this._tipPos ) ? "offsetWidth" : "offsetHeight";
				this._each( function(o) {
					var node = o.node, tipNode = getTipNode(node);
					node.style.overflow = "hidden";
					tipNode.style.position = "absolute";
					//创建提示对象
					o.tip = {
						"node": tipNode,
						"show": tipShow != undefined ? tipShow : 0,
						"close": tipClose != undefined ? tipClose : -tipNode[offset]
					};
				});
			},
			"setMove": function(index){
				var maxIndex = this._nodes.length - 1;
				this._each( function(o, i) {
					var tip = o.tip;
					if ( this._reverse ) { i = maxIndex -i; }
					tip.target = index == undefined || index != i ? tip.close : tip.show;
					tip.begin = tip.current; tip.change = tip.target - tip.begin;
				});
			},
			"tweenMove": function(){
				this._setTipPos( function(tip) {
					return this.tween( this._time, tip.begin, tip.change, this.duration );
				});
			},
			"targetMove": function(){
				this._setTipPos( function(tip){ return tip.target; });
			},
			"defaultMove": function(){
				this._setTipPos( function(tip){ return tip.close; });
			},
			"dispose": function(){
				this._each( function(o){ o.tip = null; });
			}
		},
		prototype = {
			//设置坐标值函数
			_setTipPos: function(method) {
				var pos = this._tipPos;
				this._each( function(o, i) {
					var tip = o.tip;
					tip.node.style[ pos ] = (tip.current = Math.round(method.call( this, tip ))) + "px";
				});
			}
		};
	return function(){
		var options = arguments[1];
		if ( options && options.tip == true ) {
			//扩展options
			$$.extend( options, {
				tipPos:		"bottom",//提示位置
				tipTag:		"*",//提示元素标签
				tipClass:	"",//提示元素样式
				tipShow:	null,//展示时目标坐标
				tipClose:	null//关闭时目标坐标
			}, false );
			//扩展属性
			$$.extend( this, prototype );
			//扩展钩子
			$$A.forEach( methods, function( method, name ){
				$$CE.addEvent( this, name, method );
			}, this );
		}
		init.apply( this, arguments );
	}
})();
