www.gusucode.com > 前后翻页的网页图片轮显代码源码程序 > 前后翻页的网页图片轮显代码/图片焦点图旋转流畅带有立体效果/图片焦点图旋转流畅带有立体效果/js/main.js

    function hw$(id) {return HW.ext(document.getElementById(id));}
function hw$$(c,o,t) {return HW.getElementsByClassName(c,o,t).each(HW.ext);}
function _hw$(c,s) {return HW.ext(HW.querySelector(c,s));}
function _hw$$(c,s) {return HW.querySelectorAll(c,s).each(HW.ext);}

var HW = {
	ext:function (o) {if(o) {return HW.extendObject(o,HW._proto);}return null;},
	isIE:false,
	isMacFF:false,
	dom:{ready:false,timer:null,loaded:false},
	toRun:[],

	log:function(a) {
		if(window.console&&console.log) {console.log.apply(console,arguments);}
		return a;
	},

	error:function(a) {
		if(window.console&&console.error) {console.error.apply(console,arguments);}
		else {alert(a);}
	},

	getElementsByClassName:function(cls,n,t) {
		var rtn = [];
		n=n===null?document:n;
		t=t===null?'*':t;
		var els = n.getElementsByTagName?n.getElementsByTagName(t):document.all;
		els = (!els||!els.length) && document.all?document.all:els;
		if(cls==null){return els;}
		for (var i=0,j=0; i<els.length;i++) {
			if(this.hasClass(els[i],cls)) {
				rtn[j++] = els[i];
			}
		}
		return rtn;
	},

	querySelectorAll:function(css,scope) {
		scope = scope || document;
		return HW.CssParser(css,scope);
	},

	querySelector:function(css,scope) {
		scope = scope || document;
			var o = HW.CssParser(css,scope);
			return o.length?o[0]:null;
	},

	createNode:function(t,p,c,opts) {
		var n = document.createElement(t);
		if(c) {n.innerHTML = c;}
		n = HW.extendObject(n,opts);
		HW.ext(n);
		return p.appendChild(n);
	},

	attachEvent:function(obj,evt,fnc,def) {
		if(def === false) {
			var _f = fnc;
			fnc = function(e){HW.preventDefault(e);_f(e);}
		}
		if(window.addEventListener) {obj.addEventListener(evt, fnc, false);}
		else if(window.attachEvent) {obj.attachEvent('on'+evt, fnc);}
		else if (obj.getElementById && evt=='load') {obj.onload = fnc;}
		return obj;
	},

	detachEvent:function(obj,evt,fnc,def) {
		if(def === false) {
			var _f = fnc;
			fnc = function(e){HW.preventDefault(e);_f(e);}
		}
		if(window.removeEventListener) {obj.removeEventListener(evt, fnc, false);}
		else if(window.detachEvent) {obj.detachEvent('on'+evt, fnc);}
		return obj;
	},

	preventDefault:function(e) {
		e=e||window.event;
		if(e.preventDefault) {e.preventDefault();}
		else {e.returnValue = false;}
	},

	cancelBubble:function(e) {
		e=e||window.event;
		if(e.stopPropogation) {e.stopPropogation();}
		else {e.cancelBubble = true;}
	},

	extendObject:function(d,s) {
		d=d||{};
		for (var p in s) {d[p] = s[p];}
		return d;
	},

	addClass:function(o,c) {
		if (!this.hasClass(o,c)){
			if (o.className == "") {o.className = c;}
			else {o.className += " " + c;}
		}
		return o;
	},

	hasClass:function(o,c) {
		var p = new RegExp("(^| )" + c + "( |$)");
		if (p.test(o.className)) {return true;}
		return false;
	},

	removeClass:function(o,c) {
		var p = new RegExp("(^| )" + c + "( |$)");
		o.className = o.className.replace(p, "$1");
		o.className = o.className.replace(/ hw$/, "");
		return o;
	},

	swapClass:function(o,c) {
		HW.hasClass(o,c)?HW.removeClass(o,c):HW.addClass(o,c);
		return o;
	},

	setFade:function(o,n) {
		var agt = navigator.userAgent.toLowerCase();
		if((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1)) {
			if (n == 100) {o.style.filter = "";}
			else if (n < 0) {o.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=0);";}
			else {o.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity="+ Math.round(n) + ");";}
		}
		else {			
			o.style.MozOpacity = (Math.round(n) / 100);
			o.style.opacity = (Math.round(n) / 100);
		}
		o._alpha = n;
		return o;
	},

	setStyle:function(o,s) {
		if(o) {
			for(var i in s) {
				o.style[i] = s[i];
			}
		}
		return o;
	},

	empty:function(o) {
		while(o.firstChild) {
			o.removeChild(o.firstChild);
		}
		return o;
	},

	show:function(e,t,c,time) {
		time = time?time:this.transitionTime;
		
		if(!HW.Animate) {t = null;}
		if(e) {
			switch(t) {
				case 'slide':
					var h1 = e.offsetHeight;
					var h2 = this.getTotalSize(e);
					var s = {display:'block',height:h1+'px',overflow:'hidden'};
					HW.setStyle(e,s);
					var cb = function(){
						var s = {height:'',overflow:'',position:''};
						HW.setStyle(e,s);
						e.hidden = false;
						if(c){c();}
					};
					new HW.Animator(e,h1,h2,function(e,v){e.style.height=v+'px';},time,cb);
					break;
				default:
					e.style.display = '';
					e.hidden = false;
					if(c) {c();}
					break;
			}
		}
		return e;
	},

	hide:function(e,t,c,time) {
		time = time?time:this.transitionTime;
		
		if(!HW.Animate) {t = null;}
		
		if(e) {
			switch(t) {
				case 'slide':
					var h1 = e.offsetHeight;
					var h2 = 0;
					var s = {display:'block',height:h1+'px',overflow:'hidden'};
					HW.setStyle(e,s);
					var cb = function(){
						var s = {display:'none',height:'',overflow:'',position:''};
						HW.setStyle(e,s);
						e.hidden = true;
						if(c){c();}
					};
					new HW.Animator(e,h1,h2,function(e,v){e.style.height=v+'px';},time,cb);
					break;
				default:
					e.style.display = 'none';
					e.hidden = true;
					if(c) {c();}
					break;
			}
		}
		return e;
	},

	toggle:function(e,t,c,time) {
		if(e) {
			if(e.hidden) {
				return this.show(e,t,c,time);
			}
			else {
				return this.hide(e,t,c,time);
			}
		}
	},

	getTotalSize:function(e) {
		var newStyle = {height:'',visibility:'hidden',display:'',position:'absolute'};
		var tmp = {};
		for(s in newStyle) {
			tmp[s] = e.style[s];
			e.style[s] = newStyle[s];
		}
		var h = e.offsetHeight;
		HW.setStyle(e,tmp);
		return h;
	},

	fixIE6flicker:function() {
		var m = document.uniqueID && document.compatMode && !window.XMLHttpRequest && document.execCommand ; 
		try { 
			if(!!m) { 
				m("BackgroundImageCache", false, true);
			} 
		}
		catch(e) {};
	},

	checkLoaded:function() {
		if(HW.dom.ready){return true;}
		if(document && document.getElementsByTagName && document.getElementById && document.body) {
			clearInterval(HW.dom.timer);
			HW.dom.timer = null;
			HW.dom.ready = true;
			return true;
		}
		else {return false}
	},

	onload:function(f) {
		HW.toRun.push(f);
		if(HW.dom.loaded) {
			f();
		}
	},

	load:function() {
		if(HW.checkLoaded() && !HW.dom.loaded) {
			HW.dom.loaded = true;
			for(var i=0,j=HW.toRun.length;i<j;i++) {
				HW.toRun[i]();
			}
			if(HW.isIE) {HW.fixIE6flicker();}
		}
		else if(HW.dom.timer === null) {
			HW.dom.timer = setInterval(HW.load,10);
		}
	},

	_proto:{
		log:function() {
			return HW.log(this);
		},
		addClass:function(c) {
			return HW.addClass(this,c);
		},
		removeClass:function(c) {
			return HW.removeClass(this,c);
		},
		swapClass:function(c) {
			return HW.swapClass(this,c);
		},
		hasClass:function(c) {
			return HW.hasClass(this,c);
		},
		createNode:function(t,h,p) {
			return HW.createNode(t,this,h,p);
		},
		before:function(n) {
			return this.parentNode.insertBefore(this,n);
		},
		extendObject:function(o) {
			return HW.extendObject(this,o);
		},
		setStyle:function(s) {
			return HW.setStyle(this,s);
		},
		setFade:function(n) {
			return HW.setFade(this,n);
		},
		show:function(t,c,time) {
			return HW.show(this,t,c,time);
		},
		hide:function(t,c,time) {
			return HW.hide(this,t,c,time);
		},
		toggle:function(t,c,time) {
			return HW.toggle(this,t,c,time);
		},
		empty:function() {
			return HW.empty(this);
		},
		bind:function(e,f,c) {
			return HW.attachEvent(this,e,f,c);
		},
		unbind:function(e,f,c) {
			return HW.detachEvent(this,e,f,c);
		},
		fade:function(alpha,time,callback) {
			HW.Animate.fade(this,alpha,time,callback);
			return this;
		},
		move:function(to,time,callback) {
			HW.Animate.move(this,to,time,callback);
			return this;
		}
	}

};

(function(){
	var userAgent = navigator.userAgent.toLowerCase();
	HW.isIE  = (navigator.appVersion.indexOf("MSIE") != -1)?true:false;
	HW.isMacFF  = (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1)?true:false;
	
	if(HW.isIE) (function(){
		try {
			document.documentElement.doScroll("left");
		} catch(e) {
			setTimeout(arguments.callee,0);
			return;
		}
		HW.load();
	})();
	HW.attachEvent(document,'DOMContentLoaded',HW.load);
	HW.attachEvent(window,'load',HW.load);
})();


HW.CssParser = (function() {
	var B = /\s*,\s*/;
	var A = /\s*([\s>+~(),]|^|$)\s*/g;
	var L = /([\s>+~,]|[^(]\+|^)([#.:@])/g;
	var F = /(^|\))[^\s>+~]/g;
	var M = /(\)|^)/;
	var K = /[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;
	
	function Parser(css, scope) {
		scope = scope || document.documentElement;
		var selectors = css.split(B);
		var a = [];
		for (var i = 0; i < selectors.length; i++) {
			var o = [scope];
			var sel = Parser.clean(selectors[i]);
			for (var j = 0; j < sel.length;) {
				var prefix = sel[j++];
				var fragment = sel[j++];
				var paren = "";
				if (sel[j] == "(") {
					while (sel[j++] != ")" && j < sel.length) {
						paren += sel[j];
					}
					paren = paren.slice(0, -1);
				}
				o = Parser.get(o, prefix, fragment, paren);
			}
			a = a.concat(o);
		}
		return Parser.util.unique(a);
	}
	Parser.clean = function(selector) {
		var o = selector.replace(A, "$1")
		o = o.replace(L, "$1*$2")
		o = o.replace(F, function(s){return s.replace(M, "$1 ")});
		return o.match(K) || []
	}
	Parser.get = function(scope, prefix, fragment, paren) {
		return (Parser.selectors[prefix]) ? Parser.selectors[prefix](scope, fragment, paren) : []
	}
	Parser.util = {
		toArray: function(o) {
			var a = [];
			for (var i = 0; i < o.length; i++) {
				a.push(o[i])
			}
			return a;
		},
		unique: function(o) {
			var a = [];
			for(var i=0;i<o.length;i++) {
				if(!this.inArray(o[i],a)) {a.push(o[i]);}
			}
			return a;
		},
		inArray:function(o,a) {
			for(var j=0;j<a.length;j++) {
				if(a[j] == o) {return true;}
			}
			return false;
		}
	};
	Parser.dom = {
		isTag: function(O, N) {
			return (N == "*") || (N.toLowerCase() == O.nodeName.toLowerCase())
		},
		previousSiblingElement: function(o) {
			while ( o && o.nodeType != 1 ) {
				o = o.previousSibling
			}
			return o;
		},
		nextSiblingElement: function(o) {
			while ( o && o.nodeType != 1 ) {
				o = o.nextSibling;
			}
			return o;
		},
		hasClass: function(cls, o) {
			return (o.className || "").match("(^|\\s)" + cls + "(\\s|$)");
		},
		getByTag: function(tag, o) {
			return o.getElementsByTagName(tag);
		}
	};
	Parser.selectors = {
		"#": function(scope, id) {
			for(var i=0;i<scope.length;i++) {
				if (scope[i].getAttribute("id") == id) {
					return [scope[i]];
				}
			}
			return [];
		},
		" ": function(scope, tag) {
			var a = [];
			for(var i=0;i<scope.length;i++) {
				a = a.concat(Parser.util.toArray(Parser.dom.getByTag(tag,scope[i])));
			}
			return a
		},
		">": function(scope,child) {
			var a = [];
			for (var i=0;i<scope.length;i++) {
				var parent = scope[i];
				for (var j=0;j<parent.childNodes.length;j++) {
					var node = parent.childNodes[j];
					if (node.nodeType == 1 && Parser.dom.isTag(node, child)) {
						a.push(node);
					}
				}
			}
			return a;
		},
		".": function(scope,cls) {
			var a = [];
			for (var i=0;i<scope.length;i++) {
				var node = scope[i];
				if (Parser.dom.hasClass([cls], node)) {
					a.push(node);
				}
			}
			return a;
		},
		":": function(scope,pseudo,paren) {
			return (Parser.pseudoClasses[pseudo]) ? Parser.pseudoClasses[psuedo](scope, paren) : []
		}
	};
	Parser.pseudoClasses = {};
	return Parser;
})();



HW.Ajax = function(url,callback,vars,opts) {
	var obj = this;
	opts = HW.extendObject(HW.extendObject({},HW.Ajax.Defaults),opts);
	vars = vars?vars:null;
	this.req = new HW.Ajax.Request(url,vars,opts);
	if(typeof(callback) == 'function') {this._passResponse = callback;}
	this.req._statechange(function(o) {obj._handle(o);});
	this.req._sendRequest();
};

HW.Ajax.prototype = {
	req:{},
	_handle:function(o) {
		if(this.req.xmlHttp.readyState == 4) {
			if(this.req.xmlHttp.status.toString().match(/(2|3)([0-9]{2})/)) {
				var r = new HW.Ajax.Response(this.req.xmlHttp);
				if(this.req.cache) {
					HW.Ajax.Cache.add(this.req,r);
				}
				
				this._passResponse(r);
				return;
			}
		}
		if(o && o.constructor == Object) {
			this._passResponse(o);
		}
	},
	_passResponse:function() {return;}
};

HW.Ajax.Request = function(href,vars,opts) {
	this.href = href;
	this.vars = vars;
	this.method = opts.method;
	this.cache = opts.cache;
	this.createXmlHttpRequestObject();
};

HW.Ajax.Request.prototype = {
	xmlHttp:null,
	createXmlHttpRequestObject:function() {
		try {
			this.xmlHttp = new XMLHttpRequest();
		} catch(e) {
			var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
										"MSXML2.XMLHTTP.5.0",
										"MSXML2.XMLHTTP.4.0",
										"MSXML2.XMLHTTP.3.0",
										"MSXML2.XMLHTTP",
										"Microsoft.XMLHTTP");
			for (var i=0; i<XmlHttpVersions.length && !this.xmlHttp; i++) {
				try { 
					this.xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
				}  catch(e){}
			}
		}
	},
	_sendRequest:function(method,vars) {
		if(this.cache) {
			var c = HW.Ajax.Cache.get(this);
			if(c != null) {
				this._onreadystatechange(c);
				return;
			}
		}
		if(this.xmlHttp) {
			try {
				if (this.xmlHttp.readyState == 4 || this.xmlHttp.readyState == 0) {
					this.xmlHttp.open(this.method, this.href+(this.method=='GET'&&this.vars?'?'+this.vars:''), true);
					if(this.method == 'POST') {
						this.xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
						this.xmlHttp.setRequestHeader("Content-length", this.vars.length);
						this.xmlHttp.setRequestHeader("Connection", "close");
					}
					this.xmlHttp.send(this.vars);
				}
				else {
					if(timeoutId != -1) clearTimeout(timeoutId);  
					var obj = this;
					timeoutId = setTimeout(function(){obj.sendRequest();}, 500);
				}
			} catch(e){}
		}
	},
	_statechange:function(f) {
		this.xmlHttp.onreadystatechange = f;
		this._onreadystatechange = f;
	}
};

HW.Ajax.Response = function(xml) {
	this.contentType = xml.getResponseHeader('Content-Type')?xml.getResponseHeader('Content-Type'):'text/html';
	if(this.contentType.substr(0,4) == 'text') {
		this.xml = xml.responseXML?xml.responseXML:null;
		this.text = xml.responseText?xml.responseText:'';
	}
};
HW.Ajax.Response.prototype = {xml:null,text:null,contentType:null};

HW.Ajax.Defaults = {
	cache:false,
	method:'GET'
}

HW.Ajax.Cache = {
	_store:{},
	add:function(request,response) {
		if(!this._store[request.href]) {
			this._store[request.href] = {}
		}
		this._store[request.href][request.vars?request.vars:'__novars__'] = response;
	},
	get:function(request) {
		try{
			var response = this._store[request.href][request.vars?request.vars:'__novars__'];
		}catch(e){var response=null;}
		return response?response:null;
	}
}

HW.Animate = {
	fade:function(elm,to,time,c) {
		if(!elm._alpha && elm._alpha !== 0) {elm._alpha = 100;}
		new HW.Animator(elm,elm._alpha,to,HW.setFade,time,c);
	},
	move:function(elm,to,time,c) {
		var p = {x:elm.offsetLeft,y:elm.offsetTop}
		var f = function(o,v) {
			var dx = p.x + (to.x - p.x)*v;
			var dy = p.y + (to.y - p.y)*v;
			HW.setStyle(o,{left:dx+'px',top:dy+'px'});
		}
		var a = new HW.Animator(elm,0,1,f,time,c);
	}
};

HW.Animator = function(o,v0,v1,s,t,c) {
	if(o) {this.target = o;}
	this.setFunc = s;
	this.startValue = v0;
	this.endValue = v1;
	if(t) {this.time = t;}
	if(typeof(c) == 'function') {this.callback = c;}
	this.steps = Math.ceil(this.time/this.stepLength);
	this.stepLength = this.time/this.steps;
	this.animate();
};

HW.Animator.prototype = {
	stepLength:30,
	time:500,
	steps:20,
	setFunc:function(){},
	callback:function(){},
	set:function(v) {
		this.setFunc(this.target,v);
	},
	animate:function() {
		this.timers = [];
		var obj = this;
		var df = (this.endValue - this.startValue)/this.steps;
		if(df != 0) {
			for(var i=1,j=this.steps;i<=j;i++) {
				(function(){
					var j=i;
					obj.timers.push(setTimeout(function(){
						obj.set(obj.startValue + j*df);
					},j*obj.stepLength));
				})();
			}
			this.timers.push(setTimeout(function(){obj.callback();},this.stepLength*this.steps));
		}
		else {
			this.callback();
		}
	},
	stop:function() {
		this.timers.each(function(o){clearTimeout(o);});
	}
};

Array.prototype.each = function(f) {
	if(typeof(f) == 'function') {
		for(var i=0,j=this.length;i<j;i++) {
			f(this[i]);
		}
	}
	return this;
}

HW.Carousel = function(id,opts) {
	
	// create an options object based on default values and user inputs
	this.opts = HW.extendObject(HW.Carousel.Options,opts);
	
	// launch the rotator
	this.init(id,'phRotatingElement');
}

HW.Carousel.prototype = {
	// set the starting theta value to bring the first image to the centre
	theta:3*Math.PI/2,
	// tracks the current focussed image
	current:0,
	// tracks the previously focussed image
	previous:0,
	// stores the angles needed to bring each image to the centre
	offsets:[],
	// flag if animation is happening
	active:true,
	/*
	* init(id,cls)
	* id - id of the container element
	* cls - class of the elements to rotate
	*/
	init:function(id,cls) {
		var obj = this;
		
		// find the container element
		this.container = hw$(id);
		// if the container does not exists then exit
		if(!this.container) { return;}
		
		// set the container width
		HW.setStyle(this.container,{width:this.opts.width+'px'});
		
		// create a wrapper div for our images to get around some css issues
		this.wrapper = HW.createNode('div',this.container,'',{className:'phRotatorWrapper'});
		
		// adjust the wrapper to fit our content
		this.findBounds();
		
		// find the elements to rotate
		//this.images = _hw$('#'+id+' .'+cls);
		this.images = HW.getElementsByClassName(cls,hw$(id),'div');

		// add the left and right links
		this.drawButtons();

		for(var i=0,j=this.images.length;i<j;i++) {
			HW.addClass(this.images[i],'phPhoto');
			// place the image in the wrapper element
			this.wrapper.appendChild(this.images[i]);
			//populate the offsets array
			this.offsets[i] = this.theta + i*2*Math.PI/j;
			// add an event handler to bring content to centre
			// put in closure to allow asynchronous access to 'i'
			(function(){
				var n = obj.images.length - i;
				HW.attachEvent(obj.images[i],'click',function(){

					var targetFooter = hw$('phRotatorButtons');
					var targetButtons = HW.getElementsByClassName('p_indexButton',targetFooter,'a');
					var targetSelectedButtons = HW.getElementsByClassName('p_indexButtonSelected',targetFooter,'a');
					for(var k=targetSelectedButtons.length;k>0;k--){
						HW.removeClass(targetSelectedButtons[k-1],'p_indexButtonSelected');
					}	
					HW.addClass(targetButtons[obj.images.length - n],'p_indexButtonSelected');					

					obj.goTo(n);
					
				})
			})()
		}
		
		// render the content
		this.draw();
	},
	/*
	* findBounds()
	* sets the position and dimensions of teh wrapper depending on the options defined by the user
	*/
	findBounds:function() {
		// ensure the images fill the space allowed by calculating the width of an image at the extremities
		var dw = this.opts.image_width*this.opts.image_scale;
		this.wrapperWidth = this.opts.width-dw;
		HW.setStyle(this.wrapper,{position:'relative',left:dw/2+'px',width:this.opts.width-dw+'px',height:this.opts.height+'px'});
	},
	/*
	* drawButtons()
	* create the footer section with left and right links
	*/
	drawButtons:function() {
		var obj = this;
		// create a footer wrapper to contain the links
//		this.footer = HW.createNode('div',this.container,'',{className:'phRotatorButtons'});
		this.footer = HW.createNode('div',this.container,'',{className:'phRotatorButtons',id:'phRotatorButtons'});
		
		//create the left link and bind event handler
		var left = HW.createNode('a',this.footer,this.opts.leftLink,{className:'p_leftButton p_Button',href:'#'});
		HW.attachEvent(left,'click',function(e){
			HW.preventDefault(e);		

			var targetFooter = hw$('phRotatorButtons');
			var targetButtons = HW.getElementsByClassName('p_indexButton',targetFooter,'a');
			var targetSelectedButtons = HW.getElementsByClassName('p_indexButtonSelected',targetFooter,'a');
			for(var k=targetSelectedButtons.length;k>0;k--){
				HW.removeClass(targetSelectedButtons[k-1],'p_indexButtonSelected');
			}	
			var new_value = obj.images.length - obj.current - 1;
			HW.addClass(targetButtons[new_value],'p_indexButtonSelected');						
			obj.go(1);

					
		});
		
		// add by Ivor - start
		for(var i=0, j=this.images.length;i<j;i++){
			var button = HW.createNode('a',this.footer,i+1,{className:'p_indexButton',href:'#',id:'jsRotatorButton-'+(j-i)});
			if(i==0){ HW.addClass(button,'p_indexButtonSelected'); }
			HW.attachEvent(button,'click',function(e){
				HW.preventDefault(e);
				var target = (e.target)? e.target : e.srcElement;
				var pos = target.id.lastIndexOf("-");
				if(pos > -1){
					
					var targetFooter = hw$('phRotatorButtons');
					var targetButtons = HW.getElementsByClassName('p_indexButtonSelected',targetFooter,'a');
					for(var k=targetButtons.length;k>0;k--){
						HW.removeClass(targetButtons[k-1],'p_indexButtonSelected');
					}					
					pos = parseInt(target.id.substring(pos + 1));
					HW.addClass(target,'p_indexButtonSelected');					
					obj.goTo(pos);					
				}
			});			
		}
		// add by Ivor - end
		
		//create the right link and bind event handler
		var right = HW.createNode('a',this.footer,this.opts.rightLink,{className:'p_rightButton p_Button',href:'#'});
		HW.attachEvent(right,'click',function(e){
			HW.preventDefault(e);

			var targetFooter = hw$('phRotatorButtons');
			var targetButtons = HW.getElementsByClassName('p_indexButton',targetFooter,'a');
			var targetSelectedButtons = HW.getElementsByClassName('p_indexButtonSelected',targetFooter,'a');
			for(var k=targetSelectedButtons.length;k>0;k--){
				HW.removeClass(targetSelectedButtons[k-1],'p_indexButtonSelected');
			}	
			// as obj.current gives the value reversely, we subtract the value of obj.current
			// to find out which item is the current highlight item
			var new_value = obj.images.length - obj.current;
			// since when moving from the first item to the second item, 
			// the value of obj.current is 0 which supposes to be the value of obj.images.length,
			// therefore after the subtraction, if the new value is still equal to obj.images.length,
			// we set the new value to 0 maually to indicate this is the first item moving to the second item
			if(new_value == obj.images.length){
				new_value = 0;
			}
			// highlight the coming item
			if(new_value + 1 < obj.images.length) {
				new_value = new_value + 1;
			}else{
				new_value = 0;
			}
			HW.addClass(targetButtons[new_value],'p_indexButtonSelected');			

			obj.go(-1);


		});
	},
	/*
	* go(d)
	* rotate the content
	* d - direction to rotate (1: left, -1: right)
	*/
	go:function(d) {
		// if no current animation
		if(this.active) {
			// set the previous and current elements
			this.previous = this.current;
			this.current = this.current + d;
			this.current = (this.current+this.images.length)%this.images.length;
			
			// set active flag
			this.active = false;
			
			// start animation
			this.animate();
		}
	},
	/*
	* goTo(n)
	* rotate the content to a specific element
	* n - index of the element to bring to center
	*/
	goTo:function(n) {
		// if no current animation
		if(this.active) {
			
			// ensure n is within bounds
			n = (n + this.images.length)%this.images.length;

			// if n is the current element then fire the onclickmain event and exit
			if(n == this.current) {
				this.clickMain();
				return;
			}
			// set the previous and current elements
			this.previous = this.current;
			this.current = n;

			// set active flag
			this.active = false;
			
			// start animation
			this.animate();
		}
	},
	/*
	* draw()
	* position the elements
	*/
	draw:function() {
		for(var i=0,j=this.images.length;i<j;i++) {
			// get the angle between the current element and element 0
			var offset = i*2*Math.PI/this.images.length;
			
			// calculate the z position
			// the is roughly equivalent to z-index, but is also used to position in vertical axis
			var z = 1 + Math.sin(this.theta + offset);
			
			// calculate the x position
			var x = this.wrapperWidth/2 + this.wrapperWidth*Math.cos(this.theta + offset)/2;
			
			// calculate the y position from the z value and the tilt option
			var y = -z * this.opts.height/2 * Math.sin(this.opts.tilt);
			
			// scale the content depending on z value and the image_scale option
			var scale = (2 - (z*2*(1-this.opts.image_scale)))/(this.opts.height/2)*(this.opts.height/4);
			
			// finally set the left/top positions and content sizes
			var _top = y + this.opts.height/2 - this.opts.image_height*scale/2 + 'px';
			var _left = x - this.opts.image_width*scale/2 + 'px';
			var _height = Math.max(this.opts.image_height*scale,0) + 'px';
			var _width = Math.max(this.opts.image_width*scale,0) + 'px';
			HW.setStyle(this.images[i],{top:_top,left:_left,width:_width,height:_height});
			
			// define the elements z value
			this.images[i].z = z;
		}
		// sort the elements by z value and apply z-indexes to allow layering
		this.sortZ();
	},
	/*
	* sortZ()
	* sort the elements in z value order in the z-index
	*/
	sortZ:function() {
		// create a temp copy of this.images
		var t = [];
		for(var i=0,j=this.images.length;i<j;i++) {
			t[i] = this.images[i];
		}
		// sort by the z value
		t.sort(function(a,b){
			return b.z - a.z;
		});
		// set the z-indexes in order
		for(var i=0,j=t.length;i<j;i++) {
			t[i].style.zIndex = i;
		}
	},
	/*
	* animate()
	* animate the rotator
	*/
	animate:function() {
		var obj = this;
		// set the current and final theta values
		var v1 = this.theta
		var v2 = this.offsets[this.current];
		
		// need to make sure we always go the shortest way round from one item to the next
		// if were more than half a revolution (Math.PI) apart then increment the values by 2*Math.PI (i.e. one full revolution)
		var dt = Math.abs(v2-v1);
		while(dt > Math.PI) {
			if(v1>v2) {
				v2 += 2*Math.PI;
			}
			else {
				v1 += 2*Math.PI;
			}
			dt = Math.abs(v2-v1);
		}
		
		// create an instance of the animator object to perform animation over 500ms
		// pass setter function as this.setTheta
		// pass callback funtion as this.callback
		new HW.Animator(this,v1,v2,function(o,v){obj.setTheta(v);},500,function(){obj.callback();});
	},
	/*
	* setTheta(v)
	* move the rotator to an angle of v
	* v - the angle to move to
	*/
	setTheta:function(v) {
		this.theta = v;
		// keep theta within sensible bounds
		while(this.theta > 2*Math.PI) {this.theta -= 2*Math.PI;}
		// render the content
		this.draw();
	},
	/*
	* callback()
	* finish animation
	*/
	callback:function() {
		// reset active flag to enable links
		this.active = true;
		// if onchange is defined then call it with argument of current index
		if(typeof this.opts.onchange == 'function') {
			this.opts.onchange(this.current);
		}
	},
	/*
	* clickMain()
	* handle click on main content
	*/
	clickMain:function() {
		// if onclickmain is defined then call it with argument of current index
		if(typeof this.opts.onclickmain == 'function') {
			this.opts.onclickmain(this.current);
		}
	}
}

// define the default options for our rotator
HW.Carousel.Options = {
	// dimensions of the images
	image_width:100,
	image_height:100,
	
	// dimensions of the container
	width:900,
	height:300,
	
	// angle to view rotator at
	// values >0 will view from above
	// values <0 will view from below
	tilt:0,
	
	// set the extent to which images shoudl scale
	image_scale:0.707,
	
	// text/innerHTML of left/right links
	leftLink:'prev',
	rightLink:'next',
	
	// event handler functions
	onchange:function(n){},
	onclickmain:function(n){}
}

// Auto rotator function
HW.Carousel.autoRotator = function(){
	var btn = HW.getElementsByClassName("p_rightButton",document,'a');
	if(btn.length > 0){ 
		btn = btn[0];
		if(!btn.click) {
			btn.click=function(){
				var evt = this.ownerDocument.createEvent('MouseEvents');
				evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
				this.dispatchEvent(evt);
			}
		} else {
			btn.click();	
		}
	}	
}

// add by Ivor - start
HW.onload(function() {
	if (hw$("rotator01"))
	{
		new HW.Carousel('rotator01',{image_width:500,image_height:210,image_scale:0.8,width:610,height:212});
		setInterval(HW.Carousel.autoRotator, 7000);		
	}
});
// add by Ivor - end