/**
 * 定义滚动器的类名
 */
function Roller(toRollElement, direction, speed, rollSpan, numOfpreEle, numOfEle){
	if(!this.isLegalDirection(direction)){
			alert("滚动方向只能是 up, down, left, right 中的一个！");
			return;
		}
		if(!this.isLegalSpeed(speed)){
			alert("滚动速度只能是 fast, normal, slow 中的一个！");
			return;
		}
		if(!toRollElement){
			alert("必须将滚动器绑定到一个不为空的元素上！");
			return;
		}
		if(rollSpan<=0){
			alert("滚动距离不可小于等于零！");
			return;
		}
		if(numOfpreEle<0){
			alert("预滚动元素数量不可小于零！");
			return;
		}
		if(numOfEle<0){
			alert("滚动元素的数量不可小于零！");
			return;
		}
		var caller = this;
		toRollElement.onmouseover = function (){
			caller.isMouseOver = true; //是否鼠标悬停事件被触发的标识
		};
		toRollElement.onmouseout = function (){
			caller.isMouseOver = false;
		};
		this.frame = toRollElement;
		this.direction = direction;
		this.speed = speed;
		this.rollSpan = rollSpan;//根据速度决定每次滚动的距离
		this.numOfpreEle = numOfpreEle; //预滚动元素的个数
		this.numOfEle = numOfEle; //要滚动的容器含有的子元素个数(主要用于AJAX模式下)
		this.startRolling();
}
		
/**
 * 定义滚动器的原型
 */
Roller.prototype = {
	isHasClone : false, //在滚动之前是否已经保存过原容器的innerHTML的标识
	childIndex : 0, //全局索引，用于在滚动中动态添加子元素至容器中，定义全局索引可以避免内容重复
	cloneDiv: null, //保存原容器innerHTML的变量
	//startFlag: false, //设置开始滚动标志，为了避免每一次都重新设置第一个元素的MarginTop而加入，只有第一次加载时设置marginTop
	
	//用户指定是否为有效方向
	isLegalDirection : function(direction){
		return ["up", "down", "left", "right"].indexOf(direction) >= 0;
	},
	//用户指定是否为有效速度
	isLegalSpeed : function(speed){
		return ["fast", "normal", "slow"].indexOf(speed) >= 0;
	},

	//开始滚动
	startRolling : function(){
		this.setFrameStyle();
		if(!this.rollable()){
			return;
		}
		if(this.ensureEnoughChildren()){
			var speedNum = this.getRollSpeedNum();
			//var args = ["this.rollChildren()", speedNum];
			//window.setTimeout.apply(this, args);
			var id = new Date().getTime();
			window[id] = this;
			setInterval("window[" + id + "].rollChildren()", speedNum);//开始滚动
		}
	},

	//根据滚动速度获取相应的速度数字值
	getRollSpeedNum : function(){
		var speed = this.speed;
		if("fast" == speed){
			return 100;
		}
		if("normal" == speed){
			return 300;
		}
		if("slow" == speed){
			return 500;
		}
	},
	
	setFrameStyle : function(){
		if(this.frame){
			this.frame.style.overflow = "hidden";
		}else{
			alert("没有绑定需滚动元素的父容器！");
		}
	},
	
	//确定容器内容可以被滚动
	rollable : function(){
		if(this.frame){
			var children = this.frame.childNodes;
			return children != null && children.length > 0;
		}
		return false;
	},

	ensureEnoughChildren:function(){
		var children = this.frame.childNodes;
		if(children == null || children.length == 0){ //有时在页面用Ajax请求获取数据时可能为空
			return false; 
		}
		return true;
	},

	//滚动子元素
	rollChildren:function(){
		var frameChildren = this.frame.childNodes;
		//如果原DIV没有加载完毕，则返回，不做滚动效果
		if( this.isMouseOver || frameChildren == null || frameChildren.length < this.numOfEle){
			return;
		}
		//如果没有复制过DIV，则复制DIV
		if(!this.isHasClone){
			this.cloneDiv();
		}
		
		if(!this.ensureCloneDiv()){
			return;
		}
		
		//确保当前全局索引有效，避免造成异常
		this.ensureChildIndex();
		
		//如果当前滚动容器中元素个数少于原容器(cloneDiv)元素+预滚动元素，则添加预滚动元素至容器中，要注意加载预滚动元素只在程序开始时
		if(this.childIndex < this.numOfpreEle && frameChildren.length < this.cloneDiv.childNodes.length + this.numOfpreEle){
			this.addPreElement();
		}
		
		//开始滚动功能主体
		this.rollElement();
		
		//判断是否需要移除已经滚动至可视区域外的元素
		var top1 = frameChildren[1].offsetTop;//获得当前容器顶端第二个元素,用以监控是否需要移除其上元素
		if(top1 <= 0){//如果第二个元素已经超过顶端，则此时第一个元素肯定不可见，将全局索引对应的元素加至末尾，
			this.removeElementOutOfView();
		}
	},

	//将需滚动容器的内容复制
	cloneDiv:function(){
		this.cloneDiv = document.createElement("div"); //用于保存最原始的div内容的div，全局
		this.cloneDiv.innerHTML = this.frame.innerHTML;//赋值
		this.isHasClone = true;
	},

	//确保复制的DIV可用
	ensureCloneDiv:function(){
		var cloneDivChildren = this.cloneDiv.childNodes; //获取克隆DIV的子元素
		if(cloneDivChildren == null || cloneDivChildren.length == 0){
			return false;
		}
		return true;
	},

	//确保子元素全局索引不会越界
	ensureChildIndex:function(){
		//var children = this.frame.childNodes; //获取当前滚动DIV的子元素
		var cloneChildren = this.cloneDiv.childNodes; //获取复制DIV的子元素(个数应保持不变)
		if(this.childIndex == cloneChildren.length){ //如果已超过索引上界，则置0
			this.childIndex = 0;
		}
	},

	//添加预滚动元素
	addPreElement:function(){
		//index为一全局变量，当预滚动元素没有添加完毕并且当前滚动DIV中子元素的个数没有超过原个数+预滚动个数时，
		//为保证不会出现滚动元素中越来越多的现象
			var obj = document.createElement("div");
			//此为向上滚动的实现，创建一个与父容器第一个元素相同的div元素
			obj.innerHTML = this.cloneDiv.childNodes[this.childIndex].innerHTML; //这样确保获取的是正确的内容
			this.frame.appendChild(obj); //加入父容器的底端
			this.childIndex+=1; //避免内容重复和加入指定数量的元素，每次要做自加运算
	},

	//滚动元素效果实体函数，完成主要功能
	rollElement:function(){
		var children = this.frame.childNodes; 
		var firstChild = children[0]; //获得容器顶端第一个元素
		var top = firstChild.style.marginTop;
		if(top == null || top == 0){ //设置开始滚动的初始值，从rollSpan开始
			firstChild.style.marginTop = -this.rollSpan;
		}else{
			top = top.toLowerCase();
			var end = top.indexOf("px");
			var tmp = parseInt(top.substring(0, end));
			firstChild.style.marginTop = tmp - this.rollSpan; 
			//将第一条元素的top改为负，则可以实现上移，向下移则tmp + span
		}
	},

	//移除视图外的元素
	removeElementOutOfView:function(){
		this.frame.removeChild(this.frame.childNodes[0]);
		var temp = document.createElement("div");
		temp.innerHTML = this.cloneDiv.childNodes[this.childIndex].innerHTML;
		this.addElementToEndOfFrame(temp);
	},
	
	//添加移除的元素至文件末尾
	addElementToEndOfFrame:function(obj){
		this.frame.appendChild(obj);
		this.childIndex+=1;
	}
}

//定义公用方法
if(!window.$) {
	window.$ = function(id){
		return document.getElementById(id);
	};
}
//兼容firefox的src方法
if(!window.src){
	window.src = function(_event){
		var event = window.event || _event;
		return event.srcElement || event.target;
	};
}

//window.onload = function(){
//	var roller = new Roller();
//	roller.init($("rolling"), "up", "normal", 1, 3);
//}

//定义replaceAll方法
String.prototype.replaceAll = function(src, dest){
	if(this.length == 0){
		return "";
	}
	var regExp = new RegExp(src,"ig");
	return this.replace(regExp, dest);
}
//定义数组的indexOf方法
Array.prototype.indexOf = function(object){
	for(var i = 0 ; i < this.length; i ++){
		if(this[i] == object){
			return i;
		}
	}
	return -1;
}