Project

General

Profile

1
// Native Javascript for Bootstrap 3 | Carousel
2
// by dnp_theme
3

    
4
(function(factory){
5

    
6
  // CommonJS/RequireJS and "native" compatibility
7
  if(typeof module !== "undefined" && typeof exports == "object") {
8
    // A commonJS/RequireJS environment
9
    if(typeof window != "undefined") {
10
      // Window and document exist, so return the factory's return value.
11
      module.exports = factory();
12
    } else {
13
      // Let the user give the factory a Window and Document.
14
      module.exports = factory;
15
    }
16
  } else {
17
    // Assume a traditional browser.
18
    window.Carousel = factory();
19
  }
20

    
21
})(function(){
22

    
23
  // CAROUSEL DEFINITION
24
  // ===================
25
  var Carousel = function( element, options ) {
26
    options = options || {};
27

    
28
    this.carousel = (typeof element === 'object') ? element : document.querySelector( element );
29
    this.options = {}; //replace extend
30
    this.options.keyboard = options.keyboard === 'true' ? true : false;
31
    this.options.pause = options.pause ? options.pause : 'hover'; // false / hover
32

    
33
    // bootstrap carousel default transition duration / option
34
    this.duration = 600;
35
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false; 
36
    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
37

    
38
    var items = this.carousel.querySelectorAll('.item'), il=items.length; //this is an object
39
    this.controls = this.carousel.querySelectorAll('.carousel-control');
40
    this.prev = this.controls[0];
41
    this.next = this.controls[1];
42
    this.slides = []; for (var i = 0; i < il; i++) { this.slides.push(items[i]); } // this is an array
43
    this.indicator = this.carousel.querySelector( ".carousel-indicators" ); // object
44
    this.indicators = this.carousel.querySelectorAll( ".carousel-indicators li" ); // object
45
    this.total    = this.slides.length;
46
    this.timer    = null;
47
    this.direction  = null;
48
    this.index    = 0;
49

    
50
    if (options.interval === 'false' ) {
51
      this.options.interval = false;
52
    } else {
53
      this.options.interval = parseInt(options.interval) || 5000;
54
    }
55

    
56
    this.init();
57
  };
58

    
59
  // CAROUSEL METHODS
60
  // ================
61
  Carousel.prototype = {
62
    init: function() {
63
      if ( this.options.interval !== false ){
64
        this.cycle();
65
      }
66

    
67
      if ( this.options && this.options.pause === 'hover' && this.options.interval !== false ) {
68
        this.pause();
69
      }
70
      this.actions();
71
      this._addEventListeners();
72
    },
73
    cycle: function(e) {
74
      var self = this;
75

    
76
      self.direction = 'left';
77
      self.timer = setInterval(function() {
78
        self.index++;
79
        if( self.index == self.slides.length ) {
80
          self.index = 0;
81
        }
82
        self._slideTo( self.index, e );
83

    
84
      }, self.options.interval);
85
    },
86
    pause: function() {
87
      var self = this;
88
      var pauseHandler = function () {
89
        if ( self.options.interval !==false && !/paused/.test(self.carousel.className) ) {
90
          self.carousel.className += ' paused';
91
          clearInterval( self.timer );
92
          self.timer = null;
93
        }
94
      };
95
      var resumeHandler = function() {
96
        if ( self.options.interval !==false && /paused/.test(self.carousel.className) ) {
97
          self.cycle();
98
          self.carousel.className = self.carousel.className.replace(' paused','');
99
        }
100
      };
101
      self.carousel.addEventListener( "mouseenter", pauseHandler, false);
102
      self.carousel.addEventListener( "mouseleave", resumeHandler, false);
103
      self.carousel.addEventListener( "touchstart", pauseHandler, false);
104
      self.carousel.addEventListener( "touchend", resumeHandler, false);
105
    },
106
    _slideTo: function( next, e ) {
107
      var self = this;
108
      var active = self._getActiveIndex(); // the current active
109
      //determine type
110
      var direction = self.direction;
111
      var dr = direction === 'left' ? 'next' : 'prev';
112
      var slid = null, slide=null;
113
      
114
      //register events
115
      if (('CustomEvent' in window) && window.dispatchEvent) {
116
        slid =  new CustomEvent("slid.bs.carousel");
117
        slide = new CustomEvent("slide.bs.carousel");
118
      }
119
      if (slid) { self.carousel.dispatchEvent(slid); } //here we go with the slid
120

    
121
      self._removeEventListeners();
122
      clearInterval(self.timer);
123
      self.timer = null;
124
      self._curentPage( self.indicators[next] );
125

    
126
      if ( /slide/.test(this.carousel.className) && !(this.isIE && this.isIE < 10) ) {
127
        self.slides[next].className += (' '+dr);
128
        self.slides[next].offsetWidth;
129
        self.slides[next].className += (' '+direction);
130
        self.slides[active].className += (' '+direction);
131

    
132
        setTimeout(function() { //we're gonna fake waiting for the animation to finish, cleaner and better
133
          self._addEventListeners();
134

    
135
          self.slides[next].className += ' active';
136
          self.slides[active].className = self.slides[active].className.replace(' active','');
137

    
138
          self.slides[next].className = self.slides[next].className.replace(' '+dr,'');
139
          self.slides[next].className = self.slides[next].className.replace(' '+direction,'');
140
          self.slides[active].className = self.slides[active].className.replace(' '+direction,'');
141

    
142
          if ( self.options.interval !== false && !/paused/.test(self.carousel.className) ){
143
            clearInterval(self.timer); self.cycle();
144
          }
145
          if (slide) { self.carousel.dispatchEvent(slide); } //here we go with the slide
146
        }, self.options.duration + 100 );
147
      } else {
148
        self.slides[next].className += ' active';
149
        self.slides[next].offsetWidth;
150
        self.slides[active].className = self.slides[active].className.replace(' active','');
151
        setTimeout(function() {
152
          self._addEventListeners();
153
          if ( self.options.interval !== false && !/paused/.test(self.carousel.className) ){
154
            clearInterval(self.timer); self.cycle();
155
          }
156
          if (slide) { self.carousel.dispatchEvent(slide); } //here we go with the slide
157
        }, self.options.duration + 100 );
158
      }
159
    },
160
    _addEventListeners : function () {
161
      var self = this;
162

    
163
      self.next && self.next.addEventListener( "click", self.controlsHandler, false);
164
      self.prev && self.prev.addEventListener( "click", self.controlsHandler, false);
165

    
166
      self.indicator && self.indicator.addEventListener( "click", self.indicatorHandler, false);
167

    
168
      if (self.options.keyboard === true) {
169
        window.addEventListener('keydown', self.keyHandler, false);
170
      }
171
    },
172
    _removeEventListeners : function () { // prevent mouse bubbles while animating
173
      var self = this;
174

    
175
      self.next && self.next.removeEventListener( "click", self.controlsHandler, false);
176
      self.prev && self.prev.removeEventListener( "click", self.controlsHandler, false);
177

    
178
      self.indicator && self.indicator.removeEventListener( "click", self.indicatorHandler, false);
179

    
180
      if (self.options.keyboard === true) {
181
        window.removeEventListener('keydown', self.keyHandler, false);
182
      }
183
    },
184
    _getActiveIndex : function () {
185
      return this.slides.indexOf(this.carousel.querySelector('.item.active'))
186
    },
187
    _curentPage: function( p ) {
188
      for( var i = 0; i < this.indicators.length; ++i ) {
189
        var a = this.indicators[i];
190
        a.className = "";
191
      }
192
      if (p) p.className = "active";
193
    },
194
    actions: function() {
195
      var self = this;
196
      self.indicatorHandler = function(e) {
197
        e.preventDefault();
198
        var target = e.target;
199
        var active = self._getActiveIndex(); // the current active
200

    
201
        if ( target && !/active/.test(target.className) && target.getAttribute('data-slide-to') ) {
202
          var n = parseInt( target.getAttribute('data-slide-to'), 10 );
203

    
204
          self.index = n;
205

    
206
          if( self.index == 0 ) {
207
            self.index = 0;
208
          } else if ( self.index == self.total - 1 ) {
209
            self.index = self.total - 1;
210
          }
211

    
212
           //determine direction first
213
          if  ( (active < self.index ) || (active === self.total - 1 && self.index === 0 ) ) {
214
            self.direction = 'left'; // next
215
          } else if  ( (active > self.index) || (active === 0 && self.index === self.total -1 ) ) {
216
            self.direction = 'right'; // prev
217
          }
218
        } else { return false; }
219

    
220
        self._slideTo( self.index, e ); //Do the slide
221

    
222
      },
223

    
224
      self.controlsHandler = function (e) {
225
        var target = e.currentTarget || e.srcElement;
226
        e.preventDefault();
227

    
228
        if ( target === self.next ) {
229
          self.index++;
230
          self.direction = 'left'; //set direction first
231

    
232
          if( self.index == self.total - 1 ) {
233
            self.index = self.total - 1;
234
          } else if ( self.index == self.total ){
235
            self.index = 0
236
          }
237
        } else if ( target === self.prev ) {
238
          self.index--;
239
          self.direction = 'right'; //set direction first
240

    
241
          if( self.index == 0 ) {
242
            self.index = 0;
243
          } else if ( self.index < 0 ){
244
            self.index = self.total - 1
245
          }
246
        }
247

    
248
        self._slideTo( self.index, e ); //Do the slide
249
      }
250

    
251
      self.keyHandler = function (e) {
252

    
253
        switch (e.which) {
254
          case 39:
255
            e.preventDefault();
256
            self.index++;
257
            self.direction = 'left';
258
            if( self.index == self.total - 1 ) { self.index = self.total - 1; } else
259
            if ( self.index == self.total ){ self.index = 0 }
260
            break;
261
          case 37:
262
            e.preventDefault();
263
            self.index--;
264
            self.direction = 'right';
265
            if( self.index == 0 ) { self.index = 0; } else
266
            if ( self.index < 0 ){ self.index = self.total - 1 }
267
            break;
268
          default: return;
269
        }
270
        self._slideTo( self.index, e ); //Do the slide
271
      }
272
    }
273
  }
274

    
275
  // CAROUSEL DATA API
276
  // =================
277
  var Carousels = document.querySelectorAll('[data-ride="carousel"]'), i = 0, crl = Carousels.length;
278
  for (i;i<crl;i++) {
279
    var c = Carousels[i], options = {};
280
    options.interval = c.getAttribute('data-interval') && c.getAttribute('data-interval');
281
    options.pause = c.getAttribute('data-pause') && c.getAttribute('data-pause') || 'hover';
282
    options.keyboard = c.getAttribute('data-keyboard') && c.getAttribute('data-keyboard') || false;
283
    options.duration = c.getAttribute('data-duration') && c.getAttribute('data-duration') || false;
284
    new Carousel(c, options)
285
  }
286

    
287
  return Carousel;
288

    
289
});
(4-4/17)