Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / new_ui / ui / javascripts / foundation / foundation.orbit.js @ e4a6c3b8

History | View | Annotate | Download (14.2 kB)

1
;(function ($, window, document, undefined) {
2
  'use strict';
3

    
4
  Foundation.libs = Foundation.libs || {};
5

    
6
  Foundation.libs.orbit = {
7
    name: 'orbit',
8

    
9
    version: '4.0.0',
10

    
11
    settings: {
12
      timer_speed: 10000,
13
      animation_speed: 500,
14
      bullets: true,
15
      stack_on_small: true,
16
      container_class: 'orbit-container',
17
      stack_on_small_class: 'orbit-stack-on-small',
18
      next_class: 'orbit-next',
19
      prev_class: 'orbit-prev',
20
      timer_container_class: 'orbit-timer',
21
      timer_paused_class: 'paused',
22
      timer_progress_class: 'orbit-progress',
23
      slides_container_class: 'orbit-slides-container',
24
      bullets_container_class: 'orbit-bullets',
25
      bullets_active_class: 'active',
26
      slide_number_class: 'orbit-slide-number',
27
      caption_class: 'orbit-caption',
28
      active_slide_class: 'active',
29
      orbit_transition_class: 'orbit-transitioning'
30
    },
31

    
32
    init: function (scope, method, options) {
33
      var self = this;
34
      Foundation.inherit(self, 'data_options');
35

    
36
      if (typeof method === 'object') {
37
        $.extend(true, self.settings, method);
38
      }
39

    
40
      $('[data-orbit]', scope).each(function(idx, el) {
41
        var scoped_self = $.extend(true, {}, self);
42
        scoped_self._init(idx, el);
43
      });
44
    },
45

    
46
    _container_html: function() {
47
      var self = this;
48
      return '<div class="' + self.settings.container_class + '"></div>';
49
    },
50

    
51
    _bullets_container_html: function($slides) {
52
      var self = this,
53
          $list = $('<ol class="' + self.settings.bullets_container_class + '"></ol>');
54
      $slides.each(function(idx, slide) {
55
        var $item = $('<li data-orbit-slide-number="' + (idx+1) + '" class=""></li>');
56
        if (idx === 0) {
57
          $item.addClass(self.settings.bullets_active_class);
58
        }
59
        $list.append($item);
60
      });
61
      return $list;
62
    },
63

    
64
    _slide_number_html: function(slide_number, total_slides) {
65
      var self = this,
66
          $container = $('<div class="' + self.settings.slide_number_class + '"></div>');
67
      $container.append('<span>' + slide_number + '</span> of <span>' + total_slides + '</span>');
68
      return $container;
69
    },
70

    
71
    _timer_html: function() {
72
      var self = this;
73
      if (typeof self.settings.timer_speed === 'number' && self.settings.timer_speed > 0) {
74
        return '<div class="' + self.settings.timer_container_class
75
          + '"><span></span><div class="' + self.settings.timer_progress_class
76
          + '"></div></div>';
77
      } else {
78
        return '';
79
      }
80
    },
81

    
82
    _next_html: function() {
83
      var self = this;
84
      return '<a href="#" class="' + self.settings.next_class + '">Next <span></span></a>';
85
    },
86

    
87
    _prev_html: function() {
88
      var self = this;
89
      return '<a href="#" class="' + self.settings.prev_class + '">Prev <span></span></a>';
90
    },
91

    
92
    _init: function (idx, slider) {
93
      var self = this,
94
          $slides_container = $(slider),
95
          $container = $slides_container.wrap(self._container_html()).parent(),
96
          $slides = $slides_container.children();
97
      
98
      $.extend(true, self.settings, self.data_options($slides_container));
99

    
100
      $container.append(self._prev_html());
101
      $container.append(self._next_html());
102
      $slides_container.addClass(self.settings.slides_container_class);
103
      if (self.settings.stack_on_small) {
104
        $container.addClass(self.settings.stack_on_small_class);
105
      }
106
      $container.append(self._slide_number_html(1, $slides.length));
107
      $container.append(self._timer_html());
108
      if (self.settings.bullets) {
109
        $container.after(self._bullets_container_html($slides));
110
      }
111
      // To better support the "sliding" effect it's easier
112
      // if we just clone the first and last slides
113
      $slides_container.append($slides.first().clone().attr('data-orbit-slide',''));
114
      $slides_container.prepend($slides.last().clone().attr('data-orbit-slide',''));
115
      // Make the first "real" slide active
116
      $slides_container.css('marginLeft', '-100%');
117
      $slides.first().addClass(self.settings.active_slide_class);
118

    
119
      self._init_events($slides_container);
120
      self._init_dimensions($slides_container);
121
      self._start_timer($slides_container);
122
    },
123

    
124
    _init_events: function ($slides_container) {
125
      var self = this,
126
          $container = $slides_container.parent();
127

    
128
      $(window)
129
        .on('load.fndtn.orbit', function() {
130
          $slides_container.height('');
131
          $slides_container.height($slides_container.height($container.height()));
132
          $slides_container.trigger('orbit:ready');
133
        })
134
        .on('resize.fndtn.orbit', function() {
135
          $slides_container.height('');
136
          $slides_container.height($slides_container.height($container.height()));
137
        });
138

    
139
      $(document).on('click.fndtn.orbit', '[data-orbit-link]', function(e) {
140
        e.preventDefault();
141
        var id = $(e.currentTarget).attr('data-orbit-link'),
142
            $slide = $slides_container.find('[data-orbit-slide=' + id + ']').first();
143

    
144
        if ($slide.length === 1) {
145
          self._reset_timer($slides_container, true);
146
          self._goto($slides_container, $slide.index(), function() {});
147
        }
148
      });
149

    
150
      $container.siblings('.' + self.settings.bullets_container_class)
151
        .on('click.fndtn.orbit', '[data-orbit-slide-number]', function(e) {
152
          e.preventDefault();
153
          self._reset_timer($slides_container, true);
154
          self._goto($slides_container, $(e.currentTarget).data('orbit-slide-number'),function() {});
155
        });
156

    
157
      $container
158
        .on('orbit:after-slide-change.fndtn.orbit', function(e, orbit) {
159
          var $slide_number = $container.find('.' + self.settings.slide_number_class);
160

    
161
          if ($slide_number.length === 1) {
162
            $slide_number.replaceWith(self._slide_number_html(orbit.slide_number, orbit.total_slides));
163
          }
164
        })
165
        .on('orbit:next-slide.fndtn.orbit click.fndtn.orbit', '.' + self.settings.next_class, function(e) {
166
          e.preventDefault();
167
          self._reset_timer($slides_container, true);
168
          self._goto($slides_container, 'next', function() {});
169
        })
170
        .on('orbit:prev-slide.fndtn.orbit click.fndtn.orbit', '.' + self.settings.prev_class, function(e) {
171
          e.preventDefault();
172
          self._reset_timer($slides_container, true);
173
          self._goto($slides_container, 'prev', function() {});
174
        })
175
        .on('orbit:toggle-play-pause.fndtn.orbit click.fndtn.orbit touchstart.fndtn.orbit', '.' + self.settings.timer_container_class, function(e) {
176
          e.preventDefault();
177
          var $timer = $(e.currentTarget).toggleClass(self.settings.timer_paused_class),
178
              $slides_container = $timer.closest('.' + self.settings.container_class)
179
                .find('.' + self.settings.slides_container_class);
180

    
181
          if ($timer.hasClass(self.settings.timer_paused_class)) {
182
            self._stop_timer($slides_container);
183
          } else {
184
            self._start_timer($slides_container);
185
          }
186
        })
187
        .on('touchstart.fndtn.orbit', function(e) {
188
          if (!e.touches) { e = e.originalEvent; }
189
          var data = {
190
            start_page_x: e.touches[0].pageX,
191
            start_page_y: e.touches[0].pageY,
192
            start_time: (new Date()).getTime(),
193
            delta_x: 0,
194
            is_scrolling: undefined
195
          };
196
          $container.data('swipe-transition', data);
197
          e.stopPropagation();
198
        })
199
        .on('touchmove.fndtn.orbit', function(e) {
200
          if (!e.touches) { e = e.originalEvent; }
201
          // Ignore pinch/zoom events
202
          if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
203

    
204
          var data = $container.data('swipe-transition');
205
          if (typeof data === 'undefined') {
206
            data = {};
207
          }
208

    
209
          data.delta_x = e.touches[0].pageX - data.start_page_x;
210

    
211
          if ( typeof data.is_scrolling === 'undefined') {
212
            data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
213
          }
214

    
215
          if (!data.is_scrolling && !data.active) {
216
            e.preventDefault();
217
            self._stop_timer($slides_container);
218
            var direction = (data.delta_x < 0) ? 'next' : 'prev';
219
            data.active = true;
220
            self._goto($slides_container, direction, function() {});
221
          }
222
        })
223
        .on('touchend.fndtn.orbit', function(e) {
224
          $container.data('swipe-transition', {});
225
          e.stopPropagation();
226
        });
227
    },
228

    
229
    _init_dimensions: function ($slides_container) {
230
      var $container = $slides_container.parent(),
231
          $slides = $slides_container.children();
232

    
233
      $slides_container.css('width', $slides.length * 100 + '%');
234
      $slides.css('width', 100 / $slides.length + '%');
235
      $slides_container.height($container.height());
236
      $slides_container.css('width', $slides.length * 100 + '%');
237
    },
238

    
239
    _start_timer: function ($slides_container) {
240
      var self = this,
241
          $container = $slides_container.parent();
242

    
243
      var callback = function() {
244
        self._reset_timer($slides_container, false);
245
        self._goto($slides_container, 'next', function() {
246
          self._start_timer($slides_container);
247
        });
248
      };
249

    
250
      var $timer = $container.find('.' + self.settings.timer_container_class),
251
          $progress = $timer.find('.' + self.settings.timer_progress_class),
252
          progress_pct = ($progress.width() / $timer.width()),
253
          delay = self.settings.timer_speed - (progress_pct * self.settings.timer_speed);
254

    
255
      $progress.animate({'width': '100%'}, delay, 'linear', callback);
256
      $slides_container.trigger('orbit:timer-started');
257
    },
258

    
259
    _stop_timer: function ($slides_container) {
260
      var self = this,
261
          $container = $slides_container.parent(),
262
          $timer = $container.find('.' + self.settings.timer_container_class),
263
          $progress = $timer.find('.' + self.settings.timer_progress_class),
264
          progress_pct = $progress.width() / $timer.width()
265
      self._rebuild_timer($container, progress_pct * 100 + '%');
266
      // $progress.stop();
267
      $slides_container.trigger('orbit:timer-stopped');
268
      $timer = $container.find('.' + self.settings.timer_container_class);
269
      $timer.addClass(self.settings.timer_paused_class);
270
    },
271

    
272
    _reset_timer: function($slides_container, is_paused) {
273
      var self = this,
274
          $container = $slides_container.parent();
275
      self._rebuild_timer($container, '0%');
276
      if (typeof is_paused === 'boolean' && is_paused) {
277
        var $timer = $container.find('.' + self.settings.timer_container_class);
278
        $timer.addClass(self.settings.timer_paused_class);
279
      }
280
    },
281

    
282
    _rebuild_timer: function ($container, width_pct) {
283
      // Zepto is unable to stop animations since they
284
      // are css-based. This is a workaround for that
285
      // limitation, which rebuilds the dom element
286
      // thus stopping the animation
287
      var self = this,
288
          $timer = $container.find('.' + self.settings.timer_container_class),
289
          $new_timer = $(self._timer_html()),
290
          $new_timer_progress = $new_timer.find('.' + self.settings.timer_progress_class);
291

    
292
      if (typeof Zepto === 'function') {
293
        $timer.remove();
294
        $container.append($new_timer);
295
        $new_timer_progress.css('width', width_pct);
296
      } else if (typeof jQuery === 'function') {
297
        var $progress = $timer.find('.' + self.settings.timer_progress_class);
298
        $progress.css('width', width_pct);
299
        $progress.stop();
300
      }
301
    },
302

    
303
    _goto: function($slides_container, index_or_direction, callback) {
304
      var self = this,
305
          $container = $slides_container.parent(),
306
          $slides = $slides_container.children(),
307
          $active_slide = $slides_container.find('.' + self.settings.active_slide_class),
308
          active_index = $active_slide.index();
309

    
310
      if ($container.hasClass(self.settings.orbit_transition_class)) {
311
        return false;
312
      }
313

    
314
      if (index_or_direction === 'prev') {
315
        if (active_index === 0) {
316
          active_index = $slides.length - 1;
317
        }
318
        else {
319
          active_index--;
320
        }
321
      }
322
      else if (index_or_direction === 'next') {
323
        active_index = (active_index+1) % $slides.length;
324
      }
325
      else if (typeof index_or_direction === 'number') {
326
        active_index = (index_or_direction % $slides.length);
327
      }
328
      if (active_index === ($slides.length - 1) && index_or_direction === 'next') {
329
        $slides_container.css('marginLeft', '0%');
330
        active_index = 1;
331
      }
332
      else if (active_index === 0 && index_or_direction === 'prev') {
333
        $slides_container.css('marginLeft', '-' + ($slides.length - 1) * 100 + '%');
334
        active_index = $slides.length - 2;
335
      }
336
      // Start transition, make next slide active
337
      $container.addClass(self.settings.orbit_transition_class);
338
      $active_slide.removeClass(self.settings.active_slide_class);
339
      $($slides[active_index]).addClass(self.settings.active_slide_class);
340
      // Make next bullet active
341
      var $bullets = $container.siblings('.' + self.settings.bullets_container_class);
342
      if ($bullets.length === 1) {
343
        $bullets.children().removeClass(self.settings.bullets_active_class);
344
        $($bullets.children()[active_index-1]).addClass(self.settings.bullets_active_class);
345
      }
346
      var new_margin_left = '-' + (active_index * 100) + '%';
347
      // Check to see if animation will occur, otherwise perform
348
      // callbacks manually
349
      $slides_container.trigger('orbit:before-slide-change');
350
      if ($slides_container.css('marginLeft') === new_margin_left) {
351
        $container.removeClass(self.settings.orbit_transition_class);
352
        $slides_container.trigger('orbit:after-slide-change', [{slide_number: active_index, total_slides: $slides_container.children().length - 2}]);
353
        callback();
354
      } else {
355
        $slides_container.animate({
356
          'marginLeft' : new_margin_left
357
        }, self.settings.animation_speed, 'linear', function() {
358
          $container.removeClass(self.settings.orbit_transition_class);
359
          $slides_container.trigger('orbit:after-slide-change', [{slide_number: active_index, total_slides: $slides_container.children().length - 2}]);
360
          callback();
361
        });
362
      }
363
    }
364
  };
365
}(Foundation.zj, this, this.document));