123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740 |
- /*
- * TouchSlider
- * @author qiqiboy
- * @github https://github.com/qiqiboy/touchslider
- */
- ;
- (function(ROOT, struct, undefined){
- "use strict";
- var VERSION='2.0.1';
- var lastTime=0,
- nextFrame=ROOT.requestAnimationFrame ||
- ROOT.webkitRequestAnimationFrame ||
- ROOT.mozRequestAnimationFrame ||
- ROOT.msRequestAnimationFrame ||
- function(callback){
- var currTime=+new Date,
- delay=Math.max(1000/60,1000/60-(currTime-lastTime));
- lastTime=currTime+delay;
- return setTimeout(callback,delay);
- },
- cancelFrame=ROOT.cancelAnimationFrame ||
- ROOT.webkitCancelAnimationFrame ||
- ROOT.webkitCancelRequestAnimationFrame ||
- ROOT.mozCancelRequestAnimationFrame ||
- ROOT.msCancelRequestAnimationFrame ||
- clearTimeout,
- DOC=ROOT.document,
- divstyle=DOC.createElement('div').style,
- cssVendor=function(){
- var tests="-webkit- -moz- -o- -ms-".split(" "),
- prop;
- while(prop=tests.shift()){
- if(camelCase(prop+'transform') in divstyle){
- return prop;
- }
- }
- return '';
- }(),
- transition=cssTest('transition'),
- toString=Object.prototype.toString,
- slice=[].slice,
- class2type={},
- event2type={},
- event2code={
- click:4,
- mousewheel:5,
- dommousescroll:5,
- keydown:6,
- resize:7
- },
- POINTERTYPES={
- 2:'touch',
- 3:'pen',
- 4:'mouse',
- pen:'pen'
- },
- STARTEVENT=[],
- MOVEEVENT=[],
- EVENT=function(){
- var ret={},
- states={
- start:1,
- down:1,
- move:2,
- end:3,
- up:3,
- cancel:3
- };
- each("mouse touch pointer MSPointer-".split(" "),function(prefix){
- var _prefix=/pointer/i.test(prefix)?'pointer':prefix;
- ret[_prefix]=ret[_prefix]||{};
- POINTERTYPES[_prefix]=_prefix;
- each(states,function(endfix,code){
- var ev=camelCase(prefix+endfix);
- ret[_prefix][ev]=code;
- event2type[ev.toLowerCase()]=_prefix;
- event2code[ev.toLowerCase()]=code;
- if(code==1){
- STARTEVENT.push(ev);
- }else{
- MOVEEVENT.push(ev);
- }
- });
- });
- each("otransitionend oTransitionEnd webkitTransitionEnd mozTransitionEnd MSTransitionEnd transitionend".split(" "),function(ev){
- STARTEVENT.push(ev);
- event2code[ev.toLowerCase()]=8;
- });
- return ret;
- }(),
- POINTERS={
- touch:{},
- pointer:{},
- mouse:{}
- };
- each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(name){
- class2type["[object "+name+"]"]=name.toLowerCase();
- });
- function type(obj){
- if(obj==null){
- return obj+"";
- }
-
- return typeof obj=='object'||typeof obj=='function' ? class2type[toString.call(obj)]||"object" :
- typeof obj;
- }
-
- function isArrayLike(elem){
- var tp=type(elem);
- return !!elem && tp!='function' && tp!='string' && (elem.length===0 || elem.length && (elem.nodeType==1 || (elem.length-1) in elem));
- }
- function camelCase(str){
- return (str+'').replace(/^-ms-/, 'ms-').replace(/-([a-z]|[0-9])/ig, function(all, letter){
- return (letter+'').toUpperCase();
- });
- }
- function cssTest(name){
- var prop=camelCase(name),
- _prop=camelCase(cssVendor+prop);
- return (prop in divstyle) && prop || (_prop in divstyle) && _prop || '';
- }
- function isFunction(func){
- return type(func)=='function';
- }
- function pointerLength(obj){
- var len=0,key;
- if(type(obj.length)=='number'){
- len=obj.length;
- }else if('keys' in Object){
- len=Object.keys(obj).length;
- }else{
- for(key in obj){
- if(obj.hasOwnProperty(key)){
- len++;
- }
- }
- }
- return len;
- }
- function pointerItem(obj,n){
- return 'item' in obj?obj.item(n):function(){
- var i=0,key;
- for(key in this){
- if(i++==n){
- return this[key];
- }
- }
- }.call(obj,n);
- }
-
- function each(arr, iterate){
- if(isArrayLike(arr)){
- if(type(arr.forEach)=='function'){
- return arr.forEach(iterate);
- }
- var i=0,len=arr.length,item;
- for(;i<len;i++){
- item=arr[i];
- if(type(item)!='undefined'){
- iterate(item,i,arr);
- }
- }
- }else{
- var key;
- for(key in arr){
- iterate(key,arr[key],arr);
- }
- }
- }
- function children(elem){
- var ret=[];
- each(elem.children||elem.childNodes,function(elem){
- if(elem.nodeType==1){
- ret.push(elem);
- }
- });
- return ret;
- }
- function getStyle(elem,prop){
- var style=ROOT.getComputedStyle&&ROOT.getComputedStyle(elem,null)||elem.currentStyle||elem.style;
- return style[prop];
- }
- function setStyle(elem,props){
- each(props,function(name,value){
- var prop;
- switch(name){
- case 'float':
- prop=cssTest('cssFloat')?'cssFloat':'styleFloat';
- break;
- default:
- prop=camelCase(name);
- }
- try{
- elem.style[prop]=value;
- }catch(e){}
- });
- }
- function addListener(elem,evstr,handler){
- if(type(evstr)=='object'){
- return each(evstr,function(evstr,handler){
- addListener(elem,evstr,handler);
- });
- }
- each(evstr.split(" "),function(ev){
- if(elem.addEventListener){
- elem.addEventListener(ev,handler,false);
- }else if(elem.attachEvent){
- elem.attachEvent('on'+ev,handler);
- }else elem['on'+ev]=handler;
- });
- }
- function offListener(elem,evstr,handler){
- if(type(evstr)=='object'){
- return each(evstr,function(evstr,handler){
- offListener(elem,evstr,handler);
- });
- }
- each(evstr.split(" "),function(ev){
- if(elem.removeEventListener){
- elem.removeEventListener(ev,handler,false);
- }else if(elem.detachEvent){
- elem.detachEvent('on'+ev,handler);
- }else elem['on'+ev]=null;
- });
- }
- function removeRange(){
- var range;
- if(ROOT.getSelection){
- range=getSelection();
- if('empty' in range)range.empty();
- else if('removeAllRanges' in range)range.removeAllRanges();
- }else{
- DOC.selection.empty();
- }
- }
- function EASE(t,b,c,d){
- return -c * ((t=t/d-1)*t*t*t - 1) + b;
- }
- function filterEvent(oldEvent){
- var ev={},
- which=oldEvent.which,
- button=oldEvent.button,
- pointers,pointer;
- each("wheelDelta detail which keyCode".split(" "),function(prop){
- ev[prop]=oldEvent[prop];
- });
- ev.oldEvent=oldEvent;
-
- ev.type=oldEvent.type.toLowerCase();
- ev.eventType=event2type[ev.type]||ev.type;
- ev.eventCode=event2code[ev.type]||0;
- ev.pointerType=POINTERTYPES[oldEvent.pointerType]||oldEvent.pointerType||ev.eventType;
- ev.target=oldEvent.target||oldEvent.srcElement||DOC.documentElement;
- if(ev.target.nodeType===3){
- ev.target=ev.target.parentNode;
- }
- ev.preventDefault=function(){
- oldEvent.preventDefault && oldEvent.preventDefault();
- ev.returnValue=oldEvent.returnValue=false;
- }
- if(pointers=POINTERS[ev.eventType]){
- switch(ev.eventType){
- case 'mouse':
- case 'pointer':
- var id=oldEvent.pointerId||0;
- ev.eventCode==3?delete pointers[id]:pointers[id]=oldEvent;
- break;
- case 'touch':
- POINTERS[ev.eventType]=pointers=oldEvent.touches;
- break;
- }
- if(pointer=pointerItem(pointers,0)){
- ev.clientX=pointer.clientX;
- ev.clientY=pointer.clientY;
- }
-
- ev.button=which<4?Math.max(0,which-1):button&4&&1||button&2; // left:0 middle:1 right:2
- ev.length=pointerLength(pointers);
- }
- return ev;
- }
- struct.prototype={
- version:VERSION,
- constructor:struct,
- latestTime:0,
- init:function(config){
- var self=this,
- handler=this.handler=function(ev){
- self.handleEvent(ev);
- }
- this.events={};
- this.duration=isNaN(parseInt(config.duration))?600:parseInt(config.duration);
- this.direction=parseInt(config.direction)==0?0:1;
- this.current=parseInt(config.start)||0;
- this.mouse=config.mouse==null?true:!!config.mouse;
- this.mousewheel=!!config.mousewheel;
- this.interval=parseInt(config.interval)||5000;
- this.playing=config.autoplay==null?true:!!config.autoplay;
- this.arrowkey=!!config.arrowkey;
- this.fullsize=config.fullsize==null?true:!!config.fullsize;
- this.align=config.align||'center';
- this.pages=children(this.container);
- this.length=this.pages.length;
- this.pageData=[];
- addListener(this.container,STARTEVENT.join(" ")+" click"+(this.mousewheel?" mousewheel DOMMouseScroll":""),handler);
- addListener(DOC,MOVEEVENT.join(" ")+(this.arrowkey?" keydown":""),handler);
- addListener(ROOT,'resize',handler);
-
- each(this.pages,function(page){
- self.pageData.push({
- cssText:page.style.cssText||''
- });
- });
- this.pageData.container=this.container.style.cssText||'';
- this.on({
- before:function(){clearTimeout(this.playTimer);},
- dragStart:function(){clearTimeout(this.playTimer);removeRange();},
- after:this.firePlay
- }).firePlay();
- this.comment=document.createComment(' Powered by TouchSlider v'+this.version+' https://github.com/qiqiboy/touchslider ');
- this.container.appendChild(this.comment);
- this.resize();
- },
- resize:function(){
- var self=this,
- type=this.direction?'height':'width',
- pst=getStyle(this.container,'position'),
- css;
- this.size=this.getSize(this.offsetParent=this.container[pst=='absolute'||pst=='fixed'?'offsetParent':'parentNode']||DOC.body);
- css={
- float:'left',
- display:'inline'
- }
- each(this.pages,function(page){
- if(self.fullsize){
- css[type]=self.size-self.getMarginSize(page)-self.getPaddingSize(page)-self.getBorderSize(page)+'px';
- }
- if(type=='height'){
- css['clear']='both';
- }
- setStyle(page,css);
- });
- this.total=this.getSum(0,this.length);
-
- css={};
- if(pst=='static'){
- css={position:'relative'};
- }
- css[transition]='none';
- css[type]=this.total+'px';
- css[this.direction?'top':'left']=this.getPos(this.current)+'px';
- cancelFrame(this.timer);
- setStyle(this.container,css);
- clearTimeout(this.playTimer);
- return this.firePlay();
- },
- on:function(ev,callback){
- var self=this;
- if(type(ev)=='object'){
- each(ev,function(ev,callback){
- self.on(ev,callback);
- });
- }else{
- if(!this.events[ev]){
- this.events[ev]=[];
- }
- this.events[ev].push(callback);
- }
- return this;
- },
- fire:function(ev){
- var self=this,
- args=slice.call(arguments,1);
- each(this.events[ev]||[],function(func){
- if(isFunction(func)){
- func.apply(self,args);
- }
- });
- return this;
- },
- isStatic:function(){
- return !this.timer && !this.drag;
- },
- prev:function(){
- return this.slide((this.current-1+this.length)%this.length);
- },
- next:function(){
- return this.slide((this.current+1)%this.length);
- },
- play:function(){
- this.playing=true;
- return this.firePlay();
- },
- firePlay:function(){
- var self=this;
- if(this.playing){
- this.playTimer=setTimeout(function(){
- self.next();
- },this.interval);
- }
- return this;
- },
- pause:function(){
- this.playing=false;
- clearTimeout(this.playTimer);
- return this;
- },
- slide:function(_index){
- var self=this,
- dir=this.direction,
- stime=+new Date,
- duration=this.duration,
- current=this.current,
- index=Math.min(Math.max(0,_index),this.length-1),
- curSize=this.getSum(index,index+1),
- curPos=parseFloat(getStyle(this.container,dir?'top':'left'))||0,
- type=dir?'top':'left',
- css={},tarPos;
-
- tarPos=this.getPos(index);
- duration*=Math.min(1,Math.abs(tarPos-curPos)/curSize)||10;
- this.current=index;
- this.latestTime=stime+duration;
- this.fire('before',current,index);
- this.end=function(){
- delete self.timer;
- self.fire('after',index,current);
- }
- if(transition){
- this.timer=1;
- css[transition]=type+' '+duration+'ms ease';
- css[type]=tarPos+'px';
- setStyle(this.container,css);
- }else{
- cancelFrame(this.timer);
- ani();
- }
- function ani(){
- var offset=Math.min(duration,+new Date-stime),
- s=EASE(offset,0,1,duration)
- cp=(tarPos-curPos)*s+curPos;
- self.container.style[type]=cp+'px';
- if(offset==duration){
- self.end();
- }else{
- self.timer=nextFrame(ani);
- }
- }
- },
- handleEvent:function(oldEvent){
- var ev=filterEvent(oldEvent),
- canDrag=ev.button<1&&ev.length<2&&(!this.pointerType||this.pointerType==ev.eventType)&&(this.mouse||ev.pointerType!='mouse');
- switch(ev.eventCode){
- case 2:
- if(canDrag&&this.rect){
- var index=this.current,
- dir=this.direction,
- rect=[ev.clientX,ev.clientY],
- _rect=this.rect,
- offset=rect[dir]-_rect[dir];
- if(this.drag==null && _rect.toString()!=rect.toString()){
- this.drag=Math.abs(offset)>=Math.abs(rect[1-dir]-_rect[1-dir]);
- this.drag && this.fire('dragStart',ev);
- }
- if(this.drag){
- if(!this.pages[index+(offset>0?-1:1)]){
- offset/=Math.abs(offset)/this.size+2;
- }
- this.container.style[dir?'top':'left']=this.startPos+offset+'px';
- this.fire('dragMove',ev);
- this._offset=offset;
- ev.preventDefault();
- }
- }
- break;
- case 1:
- case 3:
- if(canDrag){
- var self=this,
- index=this.current,
- type=this.direction?'top':'left',
- isDrag,offset,tm,nn,sub,curPos,tarPos,myWidth;
- if(ev.length&&(ev.eventCode==1||this.drag)){
- nn=ev.target.nodeName.toLowerCase();
- clearTimeout(this.eventTimer);
- if(!this.pointerType){
- this.pointerType=ev.eventType;
- }
- this.startPos=parseFloat(getStyle(this.container,type))||0;
- if(transition){
- this.container.style[transition]='none';
- }else if(this.timer){
- cancelFrame(this.timer);
- delete this.timer;
- }
- this.rect=[ev.clientX,ev.clientY];
- this.time=+new Date;
- this.container.style[type]=this.startPos+'px';
- if(ev.eventType!='touch' && (nn=='a' || nn=='img')){
- ev.preventDefault();
- }
- }else if(tm=this.time){
- offset=this._offset||0;
- isDrag=this.drag;
- curPos=this.startPos+offset;
- tarPos=this.getPos(index);
- each("rect drag time startPos _offset".split(" "),function(prop){
- delete self[prop];
- });
- if(isDrag){
- sub=offset>0?1:-1;
- while(sub*(curPos-tarPos)>this.getOuterSize(this.pages[index])/2&&this.pages[index-sub]){
- tarPos=this.getPos(index-=sub);
- }
- if(Math.abs(offset)>20&&+new Date-tm<500){
- index-=sub;
- }
-
- this.fire('dragEnd',ev);
- ev.preventDefault();
- }
- if(curPos!=tarPos){
- this.slide(index);
- }else if(isDrag){
- this.firePlay();
- }
- this.eventTimer=setTimeout(function(){
- delete self.pointerType;
- },400);
- }
- }
- break;
- case 4:
- if(this.timer){
- ev.preventDefault();
- }
- break;
- case 5:
- ev.preventDefault();
- if(this.isStatic() && +new Date-this.latestTime>Math.max(1000-this.duration,0)){
- var wd=ev.wheelDelta||-ev.detail;
- Math.abs(wd)>=3 && this[wd>0?'prev':'next']();
- }
- break;
- case 6:
- var nn=ev.target.nodeName.toLowerCase();
- if(this.isStatic() && nn!='input' && nn!='textarea' && nn!='select'){
- switch(ev.keyCode||ev.which){
- case 33:
- case 37:
- case 38:
- this.prev();
- break;
- case 32:
- case 34:
- case 39:
- case 40:
- this.next();
- break;
- case 35:
- this.slide(this.length-1);
- break;
- case 36:
- this.slide(0);
- break;
- }
- }
- break;
- case 7:
- this.resize();
- break;
- case 8:
- if(oldEvent.propertyName==(this.direction?'top':'left')){
- this.container.style[transition]='none';
- this.end();
- }
- break;
- }
- },
- getSum:function(from,to){
- var sum=0;
- while(from<to){
- sum+=this.getOuterSize(this.pages[from++],true);
- }
- return sum;
- },
- getPos:function(index){
- var type=this.direction?'Top':'Left',
- myWidth=this.getOuterSize(this.pages[index],true),
- sum=this.getSum(0,index)+this['getMargin'+type+'Size'](this.container)+this['getBorder'+type+'Size'](this.container);
- switch(this.align){
- case 'top':
- case 'left':
- return -sum;
- case 'bottom':
- case 'right':
- return this.size-myWidth-sum;
- default:
- return (this.size-myWidth)/2-sum;
- }
- },
- getOuterSize:function(elem,withMargin){
- return elem[this.direction?'offsetHeight':'offsetWidth']+(withMargin?this.getMarginSize(elem):0);
- },
- getInnerSize:function(elem){
- return this.getOuterSize(elem)-this.getBorderSize(elem);
- },
- getSize:function(elem){
- return elem[this.direction?'offsetHeight':'offsetWidth']-this.getPaddingSize(elem)-this.getBorderSize(elem);
- },
- destroy:function(){
- var pageData=this.pageData;
- offListener(this.container,STARTEVENT.join(" ")+" click"+(this.mousewheel?" mousewheel DOMMouseScroll":""),this.handler);
- offListener(DOC,MOVEEVENT.join(" ")+(this.arrowkey?" keydown":""),this.handler);
- offListener(ROOT,'resize',this.handler);
- each(this.pages,function(page,index){
- page.style.cssText=pageData[index].cssText;
- });
- this.container.style.cssText=pageData.container;
- this.container.removeChild(this.comment);
- this.length=0;
-
- return this.pause();
- },
- refresh:function(){
- this.pages=children(this.container);
- this.length=this.pages.length;
- this.current=Math.max(Math.min(this.length-1,this.current),0);
- return this.resize();
- },
- append:function(elem,index){
- if(null==index){
- index=this.pages.length;
- }
- this.pageData.splice(index,0,{
- cssText:elem.style.cssText||''
- });
- this.container.insertBefore(elem,this.pages[index]||null);
- return this.refresh();
- },
- prepend:function(elem){
- return this.append(elem,0);
- },
- insertBefore:function(elem,index){
- return this.append(elem,index-1);
- },
- insertAfter:function(elem,index){
- return this.append(elem,index+1);
- },
- remove:function(index){
- this.container.removeChild(this.pages[index]);
- this.pageData.splice(index,1);
- return this.refresh();
- }
- }
- each("margin padding border".split(" "),function(type){
- each("Top Left Right Bottom".split(" "),function(dir){
- var prop=type+dir;
- struct.prototype[camelCase('get-'+prop)+'Size']=function(elem){
- return parseFloat(getStyle(elem,prop+(type=='border'?'Width':'')))||0;
- }
- });
- struct.prototype[camelCase('get-'+type)+'Size']=function(elem){
- return this[camelCase('get-'+type)+(this.direction?'Top':'Left')+'Size'](elem)+this[camelCase('get-'+type)+(this.direction?'Bottom':'Right')+'Size'](elem);
- }
- });
- if(typeof exports === 'object') {
- module.exports = struct;
- } else if(typeof define=='function' && define.amd){
- define('TouchSlider',function(){
- return struct;
- });
- }else ROOT.TouchSlider=struct;
- })(window, function(wrap,config){
- if(!(this instanceof arguments.callee)){
- return new arguments.callee(wrap,config);
- }
- this.container=typeof wrap=='string'?document.getElementById(wrap):wrap;
- this.init(config||{});
- });
|