たぼさんの部屋

いちょぼとのんびり

swipe.js

swipe.js

     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;

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

         // static css
         this.container.style.overflow = 'hidden';
         this.element.style.listStyle = 'none';
         this.element.style.margin = 0;

         // trigger slider initialization
         this.setup();

         // begin auto slideshow
         this.begin();

         // add event listeners
         if (this.element.addEventListener) {
            this.element.addEventListener('touchstart', this, false);
            this.element.addEventListener('touchmove', this, false);
            this.element.addEventListener('touchend', this, false);
            this.element.addEventListener('touchcancel', 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);
            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
            var containerRect = "getBoundingClientRect" in this.container;
            this.width = Math.ceil(("getBoundingClientRect" in this.container) ? this.container.getBoundingClientRect().width : this.container.offsetWidth);

            // Fix width for Android WebView (i.e. PhoneGap)
            if (this.width === 0 && typeof window.getComputedStyle === 'function') {
               this.width = window.getComputedStyle(this.container, null).width.replace('px', '');
            }

            // return immediately if measurement fails
            if (!this.width) {
               return null;
            }
            // hide slider element but keep positioning during setup
            var origVisibility = this.container.style.visibility;
            this.container.style.visibility = 'hidden';

            // dynamic css
            this.element.style.width = Math.ceil(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);

            // restore the visibility of the slider element
            this.container.style.visibility = origVisibility;

         },

         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 (this.index) {
               this.slide(this.index - 1, this.speed);

            } else {
               // if not at first slide

               this.slide(this.length - 1, this.speed);

            }
            //if first slide return to end

         },

         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) {
            switch (e.type) {
               case 'touchstart':
                  this.onTouchStart(e);
                  break;
               case 'touchmove':
                  this.onTouchMove(e);
                  break;
               case 'touchcancel' :
               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) {
            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;

            e.stopPropagation();
         },

         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)';

               e.stopPropagation();
            }

         },

         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);

            }

            e.stopPropagation();
         }
      };