/*

 * Swipe 1.0

 *

 * Brad Birdsall, Prime

 * Copyright 2011, Licensed GPL & MIT

 *

*/



window.Swipe = function(element, options) {



  // return immediately if element doesn't exist

  if (!element) return null;



  var _this = this;



  // retreive options

  this.options = options || {};

  this.index = this.options.startSlide || 0;

  this.speed = this.options.speed || 300;

  this.callback = this.options.callback || function() {};

  this.delay = this.options.auto || 0;

  this.unresize = this.options.unresize; //anjey



  // reference dom elements

  this.container = element;

  this.element = this.container.children[0]; // the slide pane



  // static css

  //this.container.style.overflow = 'hidden'; //by anjey

  this.element.style.listStyle = 'none';



  // trigger slider initialization

  this.setup();



  // begin auto slideshow

  this.begin();



  // add event listeners

  if (this.element.addEventListener) {

  	//by anjey

  	this.element.addEventListener('mousedown', this, false);

  	 

    this.element.addEventListener('touchstart', this, false);

    this.element.addEventListener('touchmove', this, false);

    this.element.addEventListener('touchend', this, false);

    this.element.addEventListener('webkitTransitionEnd', this, false);

    this.element.addEventListener('msTransitionEnd', this, false);

    this.element.addEventListener('oTransitionEnd', this, false);

    this.element.addEventListener('transitionend', this, false);

    if(!this.unresize){ // anjey

    	window.addEventListener('resize', this, false);

    }

  }



};



Swipe.prototype = {



  setup: function() {



    // get and measure amt of slides

    this.slides = this.element.children;

    this.length = this.slides.length;



    // return immediately if their are less than two slides

    if (this.length < 2) return null;



    // determine width of each slide

    this.width = this.container.getBoundingClientRect().width || this.width; //anjey

    // return immediately if measurement fails

    if (!this.width) return null;



    // hide slider element but keep positioning during setup

    this.container.style.visibility = 'hidden';



    // dynamic css

    this.element.style.width = (this.slides.length * this.width) + 'px';

    var index = this.slides.length;

    while (index--) {

      var el = this.slides[index];

      el.style.width = this.width + 'px';

      el.style.display = 'table-cell';

      el.style.verticalAlign = 'top';

    }

    // set start position and force translate to remove initial flickering

    this.slide(this.index, 0); 



    // show slider element

    this.container.style.visibility = 'visible';



  },



  slide: function(index, duration) {



    var style = this.element.style;



    // fallback to default speed

    if (duration == undefined) {

        duration = this.speed;

    }



    // set duration speed (0 represents 1-to-1 scrolling)

    style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = duration + 'ms';



    // translate to given index position

    style.MozTransform = style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';

    style.msTransform = style.OTransform = 'translateX(' + -(index * this.width) + 'px)';



    // set new index to allow for expression arguments

    this.index = index;



  },



  getPos: function() {

    

    // return current index position

    return this.index;



  },



  prev: function(delay) {



    // cancel next scheduled automatic transition, if any

    this.delay = delay || 0;

    clearTimeout(this.interval);



    // if not at first slide

    if (this.index) this.slide(this.index-1, this.speed);



  },



  next: function(delay) {



    // cancel next scheduled automatic transition, if any

    this.delay = delay || 0;

    clearTimeout(this.interval);



    if (this.index < this.length - 1) this.slide(this.index+1, this.speed); // if not last slide

    else this.slide(0, this.speed); //if last slide return to start



  },



  begin: function() {



    var _this = this;



    this.interval = (this.delay)

      ? setTimeout(function() { 

        _this.next(_this.delay);

      }, this.delay)

      : 0;

  

  },

  

  stop: function() {

    this.delay = 0;

    clearTimeout(this.interval);

  },

  

  resume: function() {

    this.delay = this.options.auto || 0;

    this.begin();

  },



  handleEvent: function(e) {

  	var that = this;

  	if(!e.touches){

  		e.touches = new Array(e);

  		e.scale = false;

  	}

    switch (e.type) {

      // by anjey

      case 'mousedown': (function(){

      		that.element.addEventListener('mousemove', that, false);

   			that.element.addEventListener('mouseup', that, false);

   			that.element.addEventListener('mouseout', that, false);

      		that.onTouchStart(e);

      })(); break;

      case 'mousemove': this.onTouchMove(e); break;

      case 'mouseup': (function(){

	      	that.element.removeEventListener('mousemove', that, false);

	   		that.element.removeEventListener('mouseup', that, false);

	   		that.element.removeEventListener('mouseout', that, false);

	      	that.onTouchEnd(e);

      })(); break;

     case 'mouseout': (function(){

      		that.element.removeEventListener('mousemove', that, false);

   			that.element.removeEventListener('mouseup', that, false);

   			that.element.removeEventListener('mouseout', that, false);

      		that.onTouchEnd(e);

      })(); break;

    	

      case 'touchstart': this.onTouchStart(e); break;

      case 'touchmove': this.onTouchMove(e); break;

      case 'touchend': this.onTouchEnd(e); break;

      case 'webkitTransitionEnd':

      case 'msTransitionEnd':

      case 'oTransitionEnd':

      case 'transitionend': this.transitionEnd(e); break;

      case 'resize': this.setup(); break;

    }

  },



  transitionEnd: function(e) {

    e.preventDefault();

    if (this.delay) this.begin();



    this.callback(e, this.index, this.slides[this.index]);



  },



  onTouchStart: function(e) {

    

    this.start = {



      // get touch coordinates for delta calculations in onTouchMove

      pageX: e.touches[0].pageX,

      pageY: e.touches[0].pageY,



      // set initial timestamp of touch sequence

      time: Number( new Date() )



    };



    // used for testing first onTouchMove event

    this.isScrolling = undefined;

    

    // reset deltaX

    this.deltaX = 0;



    // set transition time to 0 for 1-to-1 touch movement

    this.element.style.MozTransitionDuration = this.element.style.webkitTransitionDuration = 0;



  },



  onTouchMove: function(e) {



    // ensure swiping with one touch and not pinching

    if(e.touches.length > 1 || e.scale && e.scale !== 1) return;



    this.deltaX = e.touches[0].pageX - this.start.pageX;



    // determine if scrolling test has run - one time test

    if ( typeof this.isScrolling == 'undefined') {

      this.isScrolling = !!( this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.start.pageY) );

    }



    // if user is not trying to scroll vertically

    if (!this.isScrolling) {



      // prevent native scrolling 

      e.preventDefault();



      // cancel slideshow

      clearTimeout(this.interval);



      // increase resistance if first or last slide

      this.deltaX = 

        this.deltaX / 

          ( (!this.index && this.deltaX > 0               // if first slide and sliding left

            || this.index == this.length - 1              // or if last slide and sliding right

            && this.deltaX < 0                            // and if sliding at all

          ) ?                      

          ( Math.abs(this.deltaX) / this.width + 1 )      // determine resistance level

          : 1 );                                          // no resistance if false

      

      // translate immediately 1-to-1

      this.element.style.MozTransform = this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';



    }



  },



  onTouchEnd: function(e) {



    // determine if slide attempt triggers next/prev slide

    var isValidSlide = 

          Number(new Date()) - this.start.time < 250      // if slide duration is less than 250ms

          && Math.abs(this.deltaX) > 20                   // and if slide amt is greater than 20px

          || Math.abs(this.deltaX) > this.width/2,        // or if slide amt is greater than half the width



    // determine if slide attempt is past start and end

        isPastBounds = 

          !this.index && this.deltaX > 0                          // if first slide and slide amt is greater than 0

          || this.index == this.length - 1 && this.deltaX < 0;    // or if last slide and slide amt is less than 0



    // if not scrolling vertically

    if (!this.isScrolling) {



      // call slide function with slide end value based on isValidSlide and isPastBounds tests

      this.slide( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed );



    }



  }



};

