pageflow 17.0.1 → 17.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1834 @@
1
+ /*jshint trailing: false*/
2
+ /*! iScroll v5.0.4 ~ (c) 2008-2013 Matteo Spinelli ~ http://cubiq.org/license */
3
+
4
+ var IScroll = (function (window, document, Math) {
5
+
6
+ var rAF = window.requestAnimationFrame ||
7
+ window.webkitRequestAnimationFrame ||
8
+ window.mozRequestAnimationFrame ||
9
+ window.oRequestAnimationFrame ||
10
+ window.msRequestAnimationFrame ||
11
+ function (callback) { window.setTimeout(callback, 1000 / 60); };
12
+
13
+ var utils = (function () {
14
+ var me = {};
15
+
16
+ var _elementStyle = document.createElement('div').style;
17
+ var _vendor = (function () {
18
+ var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
19
+ transform,
20
+ i = 0,
21
+ l = vendors.length;
22
+
23
+ for ( ; i < l; i++ ) {
24
+ transform = vendors[i] + 'ransform';
25
+ if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
26
+ }
27
+
28
+ return false;
29
+ })();
30
+
31
+ function _prefixStyle (style) {
32
+ if ( _vendor === false ) return false;
33
+ if ( _vendor === '' ) return style;
34
+ return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
35
+ }
36
+
37
+ me.getTime = Date.now || function getTime () { return new Date().getTime(); };
38
+
39
+ me.extend = function (target, obj) {
40
+ for ( var i in obj ) {
41
+ target[i] = obj[i];
42
+ }
43
+ };
44
+
45
+ me.addEvent = function (el, type, fn, capture) {
46
+ if (el.addEventListener) {
47
+ el.addEventListener(type, fn, !!capture);
48
+ }
49
+ else {
50
+ if (typeof fn === 'function') {
51
+ el.attachEvent('on' + type, fn);
52
+ }
53
+ else {
54
+ fn.__handleEvent = fn.__handleEvent || function(e) {
55
+ e = jQuery.event.fix(e);
56
+ if (e.button === 1) { e.button = 0; }
57
+ e.wheelDelta = e.originalEvent.wheelDelta;
58
+ fn.handleEvent(e);
59
+ };
60
+ el.attachEvent('on' + type, fn.__handleEvent);
61
+ }
62
+ }
63
+ };
64
+
65
+ me.removeEvent = function (el, type, fn, capture) {
66
+ if (el.removeEventListener) {
67
+ el.removeEventListener(type, fn, !!capture);
68
+ }
69
+ else {
70
+ el.detachEvent('on' + type, fn.__handleEvent || fn);
71
+ }
72
+ };
73
+
74
+ me.momentum = function (current, start, time, lowerMargin, wrapperSize) {
75
+ var distance = current - start,
76
+ speed = time > 0 ? Math.abs(distance) / time : 0,
77
+ destination,
78
+ duration,
79
+ deceleration = 0.0006;
80
+
81
+ destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
82
+ duration = speed / deceleration;
83
+
84
+ if ( destination < lowerMargin ) {
85
+ destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
86
+ distance = Math.abs(destination - current);
87
+ duration = distance / speed;
88
+ } else if ( destination > 0 ) {
89
+ destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
90
+ distance = Math.abs(current) + destination;
91
+ duration = distance / speed;
92
+ }
93
+
94
+ return {
95
+ destination: Math.round(destination),
96
+ duration: duration
97
+ };
98
+ };
99
+
100
+ var _transform = _prefixStyle('transform');
101
+
102
+ me.extend(me, {
103
+ hasTransform: _transform !== false,
104
+ hasPerspective: _prefixStyle('perspective') in _elementStyle,
105
+ hasTouch: 'ontouchstart' in window,
106
+ hasPointer: navigator.msPointerEnabled,
107
+ hasTransition: _prefixStyle('transition') in _elementStyle
108
+ });
109
+
110
+ me.isAndroidBrowser = /Android/.test(window.navigator.appVersion) && /Version\/\d/.test(window.navigator.appVersion);
111
+
112
+ me.extend(me.style = {}, {
113
+ transform: _transform,
114
+ transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
115
+ transitionDuration: _prefixStyle('transitionDuration'),
116
+ transformOrigin: _prefixStyle('transformOrigin')
117
+ });
118
+
119
+ me.hasClass = function (e, c) {
120
+ var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
121
+ return re.test(e.className);
122
+ };
123
+
124
+ me.addClass = function (e, c) {
125
+ if ( me.hasClass(e, c) ) {
126
+ return;
127
+ }
128
+
129
+ var newclass = e.className.split(' ');
130
+ newclass.push(c);
131
+ e.className = newclass.join(' ');
132
+ };
133
+
134
+ me.removeClass = function (e, c) {
135
+ if ( !me.hasClass(e, c) ) {
136
+ return;
137
+ }
138
+
139
+ var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
140
+ e.className = e.className.replace(re, '');
141
+ };
142
+
143
+ me.isDirLtr = function (el) {
144
+ var styles = window.getComputedStyle(el);
145
+ return styles.direction != 'rtl';
146
+ };
147
+
148
+ me.offsetRight = function (e) {
149
+ return e.offsetParent ? e.offsetParent.offsetWidth - e.offsetLeft - e.offsetWidth : 0;
150
+ };
151
+
152
+ me.extend(me.eventType = {}, {
153
+ touchstart: 1,
154
+ touchmove: 1,
155
+ touchend: 1,
156
+
157
+ mousedown: 2,
158
+ mousemove: 2,
159
+ mouseup: 2,
160
+
161
+ MSPointerDown: 3,
162
+ MSPointerMove: 3,
163
+ MSPointerUp: 3
164
+ });
165
+
166
+ me.extend(me.ease = {}, {
167
+ quadratic: {
168
+ style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
169
+ fn: function (k) {
170
+ return k * ( 2 - k );
171
+ }
172
+ },
173
+ circular: {
174
+ style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
175
+ fn: function (k) {
176
+ return Math.sqrt( 1 - ( --k * k ) );
177
+ }
178
+ },
179
+ back: {
180
+ style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
181
+ fn: function (k) {
182
+ var b = 4;
183
+ return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
184
+ }
185
+ },
186
+ bounce: {
187
+ style: '',
188
+ fn: function (k) {
189
+ if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
190
+ return 7.5625 * k * k;
191
+ } else if ( k < ( 2 / 2.75 ) ) {
192
+ return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
193
+ } else if ( k < ( 2.5 / 2.75 ) ) {
194
+ return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
195
+ } else {
196
+ return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
197
+ }
198
+ }
199
+ },
200
+ elastic: {
201
+ style: '',
202
+ fn: function (k) {
203
+ var f = 0.22,
204
+ e = 0.4;
205
+
206
+ if ( k === 0 ) { return 0; }
207
+ if ( k == 1 ) { return 1; }
208
+
209
+ return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
210
+ }
211
+ }
212
+ });
213
+
214
+ me.tap = function (e, eventName) {
215
+ var ev = document.createEvent('Event');
216
+ ev.initEvent(eventName, true, true);
217
+ ev.pageX = e.pageX;
218
+ ev.pageY = e.pageY;
219
+ e.target.dispatchEvent(ev);
220
+ };
221
+
222
+ me.click = function (e) {
223
+ var target = e.target,
224
+ ev;
225
+
226
+ if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
227
+ ev = document.createEvent('MouseEvents');
228
+ ev.initMouseEvent('click', true, true, e.view, 1,
229
+ target.screenX, target.screenY, target.clientX, target.clientY,
230
+ e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
231
+ 0, null);
232
+
233
+ ev._constructed = true;
234
+ target.dispatchEvent(ev);
235
+ }
236
+ };
237
+
238
+ return me;
239
+ })();
240
+
241
+ function IScroll (el, options) {
242
+ this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
243
+ this.scroller = this.wrapper.children[0];
244
+ this.scrollerStyle = this.scroller.style; // cache style for better performance
245
+
246
+ this.options = {
247
+
248
+ resizeIndicator: true,
249
+
250
+ mouseWheelSpeed: 20,
251
+
252
+ snapThreshold: 0.334,
253
+
254
+ // INSERT POINT: OPTIONS
255
+
256
+ startX: 0,
257
+ startY: 0,
258
+ scrollY: true,
259
+ directionLockThreshold: 5,
260
+ momentum: true,
261
+
262
+ bounce: true,
263
+ bounceTime: 600,
264
+ bounceEasing: '',
265
+
266
+ preventDefault: true,
267
+
268
+ HWCompositing: true,
269
+ useTransition: true,
270
+ useTransform: true
271
+ };
272
+
273
+ for ( var i in options ) {
274
+ this.options[i] = options[i];
275
+ }
276
+
277
+ // Normalize options
278
+ this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
279
+
280
+ this.options.useTransition = utils.hasTransition && this.options.useTransition;
281
+ this.options.useTransform = utils.hasTransform && this.options.useTransform;
282
+
283
+ this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
284
+ this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
285
+
286
+ // If you want eventPassthrough I have to lock one of the axes
287
+ this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
288
+ this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
289
+
290
+ // With eventPassthrough we also need lockDirection mechanism
291
+ this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
292
+ this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
293
+
294
+ this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
295
+
296
+ this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
297
+
298
+ if ( this.options.tap === true ) {
299
+ this.options.tap = 'tap';
300
+ }
301
+
302
+ this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
303
+
304
+ if ( this.options.probeType == 3 ) {
305
+ this.options.useTransition = false; }
306
+
307
+ // INSERT POINT: NORMALIZATION
308
+
309
+ // Some defaults
310
+ this.x = 0;
311
+ this.y = 0;
312
+ this.directionX = 0;
313
+ this.directionY = 0;
314
+ this.dir = utils.isDirLtr(this.wrapper) ? 1 : -1;
315
+ this._events = {};
316
+
317
+ // INSERT POINT: DEFAULTS
318
+
319
+ this._init();
320
+ this.refresh();
321
+
322
+ this.scrollTo(this.options.startX, this.options.startY);
323
+ this.enable();
324
+ }
325
+
326
+ IScroll.prototype = {
327
+ version: '5.0.4',
328
+
329
+ _init: function () {
330
+ this._initEvents();
331
+
332
+ if ( this.options.scrollbars || this.options.indicators ) {
333
+ this._initIndicators();
334
+ }
335
+
336
+ if ( this.options.mouseWheel ) {
337
+ this._initWheel();
338
+ }
339
+
340
+ if ( this.options.snap ) {
341
+ this._initSnap();
342
+ }
343
+
344
+ if ( this.options.keyBindings ) {
345
+ this._initKeys();
346
+ }
347
+
348
+ // INSERT POINT: _init
349
+
350
+ },
351
+
352
+ destroy: function () {
353
+ this._initEvents(true);
354
+
355
+ this._execEvent('destroy');
356
+ },
357
+
358
+ _transitionEnd: function (e) {
359
+ if ( e.target != this.scroller ) {
360
+ return;
361
+ }
362
+
363
+ this._transitionTime(0);
364
+ if ( !this.resetPosition(this.options.bounceTime) ) {
365
+ this._execEvent('scrollEnd');
366
+ }
367
+ },
368
+
369
+ _start: function (e) {
370
+ // React to left mouse button only
371
+ if ( utils.eventType[e.type] != 1 ) {
372
+ if ( e.button !== 0 ) {
373
+ return;
374
+ }
375
+ }
376
+
377
+ if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
378
+ return;
379
+ }
380
+
381
+ if ( this.options.preventDefault && !utils.isAndroidBrowser ) {
382
+ e.preventDefault(); // This seems to break default Android browser
383
+ }
384
+
385
+ var point = e.touches ? e.touches[0] : e,
386
+ pos;
387
+
388
+ this.initiated = utils.eventType[e.type];
389
+ this.moved = false;
390
+ this.distX = 0;
391
+ this.distY = 0;
392
+ this.directionX = 0;
393
+ this.directionY = 0;
394
+ this.directionLocked = 0;
395
+
396
+ this._transitionTime();
397
+
398
+ this.isAnimating = false;
399
+ this.startTime = utils.getTime();
400
+
401
+ if ( this.options.useTransition && this.isInTransition ) {
402
+ pos = this.getComputedPosition();
403
+
404
+ this._translate(Math.round(pos.x), Math.round(pos.y));
405
+ this.isInTransition = false;
406
+ }
407
+
408
+ this.startX = this.x;
409
+ this.startY = this.y;
410
+ this.absStartX = this.x;
411
+ this.absStartY = this.y;
412
+ this.pointX = point.pageX;
413
+ this.pointY = point.pageY;
414
+ this.startPointX = point.pageX;
415
+ this.startPointY = point.pageY;
416
+
417
+ this._execEvent('scrollStart');
418
+ },
419
+
420
+ _move: function (e) {
421
+ if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
422
+ return;
423
+ }
424
+
425
+ if ( this.options.preventDefault ) { // increases performance on Android? TODO: check!
426
+ e.preventDefault();
427
+ }
428
+
429
+ var point = e.touches ? e.touches[0] : e,
430
+ deltaX = this.dir * (this.hasHorizontalScroll ? point.pageX - this.pointX : 0),
431
+ deltaY = this.hasVerticalScroll ? point.pageY - this.pointY : 0,
432
+ timestamp = utils.getTime(),
433
+ newX, newY,
434
+ absDistX, absDistY;
435
+
436
+ this.pointX = point.pageX;
437
+ this.pointY = point.pageY;
438
+
439
+ this.distX += deltaX;
440
+ this.distY += deltaY;
441
+ absDistX = Math.abs(this.distX);
442
+ absDistY = Math.abs(point.pageY - this.startPointY);
443
+
444
+ // We need to move at least 10 pixels for the scrolling to initiate
445
+ if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
446
+ return;
447
+ }
448
+
449
+ // If you are scrolling in one direction lock the other
450
+ if ( !this.directionLocked && !this.options.freeScroll ) {
451
+ if ( absDistX > absDistY + this.options.directionLockThreshold ) {
452
+ this.directionLocked = 'h'; // lock horizontally
453
+ } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
454
+ this.directionLocked = 'v'; // lock vertically
455
+ } else {
456
+ this.directionLocked = 'n'; // no lock
457
+ }
458
+ }
459
+
460
+ if ( this.directionLocked == 'h' ) {
461
+ if ( this.options.eventPassthrough == 'vertical' ) {
462
+ e.preventDefault();
463
+ } else if ( this.options.eventPassthrough == 'horizontal' ) {
464
+ this.initiated = false;
465
+ return;
466
+ }
467
+
468
+ deltaY = 0;
469
+ } else if ( this.directionLocked == 'v' ) {
470
+ if ( this.options.eventPassthrough == 'horizontal' ) {
471
+ e.preventDefault();
472
+ } else if ( this.options.eventPassthrough == 'vertical' ) {
473
+ this.initiated = false;
474
+ return;
475
+ }
476
+
477
+ deltaX = 0;
478
+ }
479
+
480
+ newX = this.x + deltaX;
481
+ newY = this.y + deltaY;
482
+
483
+ // Slow down if outside of the boundaries
484
+ if ( newX > 0 || newX < this.maxScrollX ) {
485
+ newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
486
+ }
487
+ if ( newY > 0 || newY < this.maxScrollY ) {
488
+ newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
489
+ }
490
+
491
+ this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
492
+ this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
493
+
494
+ this.moved = true;
495
+
496
+ this._translate(newX, newY);
497
+
498
+ /* REPLACE START: _move */
499
+ if ( timestamp - this.startTime > 300 ) {
500
+ this.startTime = timestamp;
501
+ this.startX = this.x;
502
+ this.startY = this.y;
503
+
504
+ if ( this.options.probeType == 1 ) {
505
+ this._execEvent('scroll');
506
+ }
507
+ }
508
+
509
+ if ( this.options.probeType > 1 ) {
510
+ this._execEvent('scroll');
511
+ }
512
+ /* REPLACE END: _move */
513
+
514
+ },
515
+
516
+ _end: function (e) {
517
+ if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
518
+ return;
519
+ }
520
+
521
+ if ( this.options.preventDefault ) {
522
+ e.preventDefault(); // TODO: check if needed
523
+ }
524
+
525
+ var point = e.changedTouches ? e.changedTouches[0] : e,
526
+ momentumX,
527
+ momentumY,
528
+ duration = utils.getTime() - this.startTime,
529
+ newX = Math.round(this.x),
530
+ newY = Math.round(this.y),
531
+ distanceX = Math.abs(newX - this.startX),
532
+ distanceY = Math.abs(newY - this.startY),
533
+ time = 0,
534
+ easing = '';
535
+
536
+ this.scrollTo(newX, newY); // ensures that the last position is rounded
537
+
538
+ this.isInTransition = 0;
539
+ this.initiated = 0;
540
+ this.endTime = utils.getTime();
541
+
542
+ // reset if we are outside of the boundaries
543
+ if ( this.resetPosition(this.options.bounceTime) ) {
544
+ return;
545
+ }
546
+
547
+ // we scrolled less than 10 pixels
548
+ if ( !this.moved ) {
549
+ if ( this.options.tap ) {
550
+ utils.tap(e, this.options.tap);
551
+ }
552
+
553
+ if ( this.options.click ) {
554
+ utils.click(e);
555
+ }
556
+
557
+ return;
558
+ }
559
+
560
+ if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
561
+ this._execEvent('flick');
562
+ return;
563
+ }
564
+
565
+ // start momentum animation if needed
566
+ if ( this.options.momentum && duration < 300 ) {
567
+ momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0) : { destination: newX, duration: 0 };
568
+ momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0) : { destination: newY, duration: 0 };
569
+ newX = momentumX.destination;
570
+ newY = momentumY.destination;
571
+ time = Math.max(momentumX.duration, momentumY.duration);
572
+ this.isInTransition = 1;
573
+ }
574
+
575
+ if ( this.options.snap ) {
576
+ var snap = this._nearestSnap(newX, newY);
577
+ this.currentPage = snap;
578
+ newX = snap.x;
579
+ newY = snap.y;
580
+ time = this.options.snapSpeed || Math.max(
581
+ Math.max(
582
+ Math.min(distanceX, 1000),
583
+ Math.min(distanceX, 1000)
584
+ ), 300);
585
+
586
+ this.directionX = 0;
587
+ this.directionY = 0;
588
+ easing = this.options.bounceEasing;
589
+ }
590
+
591
+ if ( newX != this.x || newY != this.y ) {
592
+ // change easing function when scroller goes out of the boundaries
593
+ if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
594
+ easing = utils.ease.quadratic;
595
+ }
596
+
597
+ this.scrollTo(newX, newY, time, easing);
598
+ return;
599
+ }
600
+
601
+ this._execEvent('scrollEnd');
602
+ },
603
+
604
+ _resize: function () {
605
+ var that = this;
606
+
607
+ clearTimeout(this.resizeTimeout);
608
+
609
+ this.resizeTimeout = setTimeout(function () {
610
+ that.refresh();
611
+ }, this.options.resizePolling);
612
+ },
613
+
614
+ resetPosition: function (time) {
615
+ var x = this.x,
616
+ y = this.y;
617
+
618
+ time = time || 0;
619
+
620
+ if ( !this.hasHorizontalScroll || this.x > 0 ) {
621
+ x = 0;
622
+ } else if ( this.x < this.maxScrollX ) {
623
+ x = this.maxScrollX;
624
+ }
625
+
626
+ if ( !this.hasVerticalScroll || this.y > 0 ) {
627
+ y = 0;
628
+ } else if ( this.y < this.maxScrollY ) {
629
+ y = this.maxScrollY;
630
+ }
631
+
632
+ if ( x == this.x && y == this.y ) {
633
+ return false;
634
+ }
635
+
636
+ this.scrollTo(x, y, time, this.options.bounceEasing);
637
+
638
+ return true;
639
+ },
640
+
641
+ disable: function () {
642
+ // Cancel scrolling
643
+ this.isInTransition = 0; // CS
644
+ this.initiated = 0; // CS
645
+ this.endTime = utils.getTime(); // CS
646
+
647
+ this.enabled = false;
648
+ },
649
+
650
+ enable: function () {
651
+ this.enabled = true;
652
+ },
653
+
654
+ refresh: function () {
655
+ var rf = this.wrapper.offsetHeight; // Force reflow
656
+
657
+ this.wrapperWidth = this.wrapper.clientWidth;
658
+ this.wrapperHeight = this.wrapper.clientHeight;
659
+
660
+ /* REPLACE START: refresh */
661
+
662
+ this.scrollerWidth = this.scroller.offsetWidth;
663
+ this.scrollerHeight = this.scroller.offsetHeight;
664
+
665
+ /* REPLACE END: refresh */
666
+
667
+ this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
668
+ this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
669
+
670
+ this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
671
+ this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
672
+
673
+ if ( !this.hasHorizontalScroll ) {
674
+ this.maxScrollX = 0;
675
+ this.scrollerWidth = this.wrapperWidth;
676
+ }
677
+
678
+ if ( !this.hasVerticalScroll ) {
679
+ this.maxScrollY = 0;
680
+ this.scrollerHeight = this.wrapperHeight;
681
+ }
682
+
683
+ this.endTime = 0;
684
+ this.directionX = 0;
685
+ this.directionY = 0;
686
+
687
+ this.wrapperOffset = this.offset(this.wrapper);
688
+
689
+ this._execEvent('refresh');
690
+
691
+ this.resetPosition();
692
+
693
+ if ( this.options.snap ) {
694
+ var snap = this._nearestSnap(this.x, this.y);
695
+ if ( this.x == snap.x && this.y == snap.y ) {
696
+ return;
697
+ }
698
+
699
+ this.currentPage = snap;
700
+ this.scrollTo(snap.x, snap.y);
701
+ }
702
+ },
703
+
704
+ on: function (type, fn) {
705
+ if ( !this._events[type] ) {
706
+ this._events[type] = [];
707
+ }
708
+
709
+ this._events[type].push(fn);
710
+ },
711
+
712
+ _execEvent: function (type, event) {
713
+ if ( !this._events[type] ) {
714
+ return;
715
+ }
716
+
717
+ var i = 0,
718
+ l = this._events[type].length;
719
+
720
+ if ( !l ) {
721
+ return;
722
+ }
723
+
724
+ for ( ; i < l; i++ ) {
725
+ this._events[type][i].call(this, event);
726
+ }
727
+ },
728
+
729
+ scrollBy: function (x, y, time, easing) {
730
+ x = this.x + x;
731
+ y = this.y + y;
732
+ time = time || 0;
733
+
734
+ this.scrollTo(x, y, time, easing);
735
+ },
736
+
737
+ scrollTo: function (x, y, time, easing) {
738
+ easing = easing || utils.ease.circular;
739
+
740
+ if ( !time || (this.options.useTransition && easing.style) ) {
741
+ this._transitionTimingFunction(easing.style);
742
+ this._transitionTime(time);
743
+ this._translate(x, y);
744
+ } else {
745
+ this._animate(x, y, time, easing.fn);
746
+ }
747
+ },
748
+
749
+ scrollToElement: function (el, time, offsetX, offsetY, easing) {
750
+ el = el.nodeType ? el : this.scroller.querySelector(el);
751
+
752
+ if ( !el ) {
753
+ return;
754
+ }
755
+
756
+ var pos = this.offset(el);
757
+
758
+ pos.x -= this.wrapperOffset.x;
759
+ pos.y -= this.wrapperOffset.y;
760
+
761
+ // if offsetX/Y are true we center the element to the screen
762
+ if ( offsetX === true ) {
763
+ offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
764
+ }
765
+ if ( offsetY === true ) {
766
+ offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
767
+ }
768
+
769
+ pos.x -= offsetX || 0;
770
+ pos.y -= offsetY || 0;
771
+
772
+ pos.x = pos.x > 0 ? 0 : pos.x < this.maxScrollX ? this.maxScrollX : pos.x;
773
+ pos.y = pos.y > 0 ? 0 : pos.y < this.maxScrollY ? this.maxScrollY : pos.y;
774
+
775
+ time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(pos.x)*2, Math.abs(pos.y)*2) : time;
776
+
777
+ this.scrollTo(pos.x, pos.y, time, easing);
778
+ },
779
+
780
+ _transitionTime: function (time) {
781
+ time = time || 0;
782
+ this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';
783
+
784
+
785
+ if ( this.indicator1 ) {
786
+ this.indicator1.transitionTime(time);
787
+ }
788
+
789
+ if ( this.indicator2 ) {
790
+ this.indicator2.transitionTime(time);
791
+ }
792
+
793
+ // INSERT POINT: _transitionTime
794
+
795
+ },
796
+
797
+ _transitionTimingFunction: function (easing) {
798
+ this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
799
+
800
+
801
+ if ( this.indicator1 ) {
802
+ this.indicator1.transitionTimingFunction(easing);
803
+ }
804
+
805
+ if ( this.indicator2 ) {
806
+ this.indicator2.transitionTimingFunction(easing);
807
+ }
808
+
809
+
810
+ // INSERT POINT: _transitionTimingFunction
811
+
812
+ },
813
+
814
+ _translate: function (x, y) {
815
+ if ( this.options.useTransform ) {
816
+
817
+ /* REPLACE START: _translate */
818
+
819
+ this.scrollerStyle[utils.style.transform] = 'translate(' + (this.dir * x) + 'px,' + y + 'px)' + this.translateZ;
820
+
821
+ /* REPLACE END: _translate */
822
+
823
+ } else {
824
+ x = Math.round(x);
825
+ y = Math.round(y);
826
+ this.scrollerStyle.left = x + 'px';
827
+ this.scrollerStyle.top = y + 'px';
828
+ }
829
+
830
+ this.x = x;
831
+ this.y = y;
832
+
833
+
834
+ if ( this.indicator1 ) { // usually the vertical
835
+ this.indicator1.updatePosition();
836
+ }
837
+
838
+ if ( this.indicator2 ) {
839
+ this.indicator2.updatePosition();
840
+ }
841
+
842
+ // INSERT POINT: _translate
843
+
844
+ },
845
+
846
+ _initEvents: function (remove) {
847
+ var eventType = remove ? utils.removeEvent : utils.addEvent,
848
+ target = this.options.bindToWrapper ? this.wrapper : window,
849
+ startEventTarget = this.options.eventListenerTarget || this.wrapper;
850
+
851
+ eventType(window, 'orientationchange', this);
852
+ eventType(window, 'resize', this);
853
+
854
+ eventType(startEventTarget, 'mousedown', this);
855
+ eventType(document, 'mousemove', this);
856
+ eventType(document, 'mousecancel', this);
857
+ eventType(document, 'mouseup', this);
858
+
859
+ if ( utils.hasPointer ) {
860
+ eventType(startEventTarget, 'MSPointerDown', this);
861
+ eventType(target, 'MSPointerMove', this);
862
+ eventType(target, 'MSPointerCancel', this);
863
+ eventType(target, 'MSPointerUp', this);
864
+ }
865
+
866
+ if ( utils.hasTouch ) {
867
+ eventType(startEventTarget, 'touchstart', this);
868
+ eventType(target, 'touchmove', this);
869
+ eventType(target, 'touchcancel', this);
870
+ eventType(target, 'touchend', this);
871
+ }
872
+
873
+ eventType(this.scroller, 'transitionend', this);
874
+ eventType(this.scroller, 'webkitTransitionEnd', this);
875
+ eventType(this.scroller, 'oTransitionEnd', this);
876
+ eventType(this.scroller, 'MSTransitionEnd', this);
877
+ },
878
+
879
+ offsetX: function (el) {
880
+ return this.dir > 0 ? el.offsetLeft : utils.offsetRight(el);
881
+ },
882
+
883
+ offset: function (el) {
884
+ var x = -this.offsetX(el),
885
+ y = -el.offsetTop;
886
+
887
+ // jshint -W084
888
+ while (el = el.offsetParent) {
889
+ x -= this.offsetX(el);
890
+ y -= el.offsetTop;
891
+ }
892
+ // jshint +W084
893
+
894
+ return {
895
+ x: x,
896
+ y: y
897
+ };
898
+ },
899
+
900
+ getComputedPosition: function () {
901
+ var matrix = window.getComputedStyle(this.scroller, null),
902
+ x, y;
903
+
904
+ if ( this.options.useTransform ) {
905
+ matrix = matrix[utils.style.transform].split(')')[0].split(', ');
906
+ x = this.dir * (matrix[12] || matrix[4]);
907
+ y = +(matrix[13] || matrix[5]);
908
+ } else {
909
+ x = +matrix.left.replace(/[^-\d]/g, '');
910
+ y = +matrix.top.replace(/[^-\d]/g, '');
911
+ }
912
+
913
+ return { x: x, y: y };
914
+ },
915
+
916
+ _initIndicators: function () {
917
+ var interactive = this.options.interactiveScrollbars,
918
+ defaultScrollbars = typeof this.options.scrollbars != 'object',
919
+ customStyle = typeof this.options.scrollbars != 'string',
920
+ indicator1,
921
+ indicator2;
922
+
923
+ if ( this.options.scrollbars ) {
924
+ // Vertical scrollbar
925
+ if ( this.options.scrollY ) {
926
+ indicator1 = {
927
+ el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
928
+ interactive: interactive,
929
+ defaultScrollbars: true,
930
+ customStyle: customStyle,
931
+ resize: this.options.resizeIndicator,
932
+ listenX: false
933
+ };
934
+
935
+ this.wrapper.appendChild(indicator1.el);
936
+ }
937
+
938
+ // Horizontal scrollbar
939
+ if ( this.options.scrollX ) {
940
+ indicator2 = {
941
+ el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
942
+ interactive: interactive,
943
+ defaultScrollbars: true,
944
+ customStyle: customStyle,
945
+ resize: this.options.resizeIndicator,
946
+ listenY: false
947
+ };
948
+
949
+ this.wrapper.appendChild(indicator2.el);
950
+ }
951
+ } else {
952
+ indicator1 = this.options.indicators.length ? this.options.indicators[0] : this.options.indicators;
953
+ indicator2 = this.options.indicators[1] && this.options.indicators[1];
954
+ }
955
+
956
+ if ( indicator1 ) {
957
+ this.indicator1 = new Indicator(this, indicator1);
958
+ }
959
+
960
+ if ( indicator2 ) {
961
+ this.indicator2 = new Indicator(this, indicator2);
962
+ }
963
+
964
+ this.on('refresh', function () {
965
+ if ( this.indicator1 ) {
966
+ this.indicator1.refresh();
967
+ }
968
+
969
+ if ( this.indicator2 ) {
970
+ this.indicator2.refresh();
971
+ }
972
+ });
973
+
974
+ this.on('destroy', function () {
975
+ if ( this.indicator1 ) {
976
+ this.indicator1.destroy();
977
+ this.indicator1 = null;
978
+ }
979
+
980
+ if ( this.indicator2 ) {
981
+ this.indicator2.destroy();
982
+ this.indicator2 = null;
983
+ }
984
+ });
985
+ },
986
+
987
+ _initWheel: function () {
988
+ var target = this.options.eventListenerTarget || this.wrapper;
989
+
990
+ utils.addEvent(target, 'wheel', this);
991
+ utils.addEvent(target, 'mousewheel', this);
992
+ utils.addEvent(target, 'DOMMouseScroll', this);
993
+
994
+ this.on('destroy', function () {
995
+ utils.removeEvent(target, 'wheel', this);
996
+ utils.removeEvent(target, 'mousewheel', this);
997
+ utils.removeEvent(target, 'DOMMouseScroll', this);
998
+ });
999
+ },
1000
+
1001
+ _wheel: function (e) {
1002
+ if ( !this.enabled ) {
1003
+ return;
1004
+ }
1005
+
1006
+ var wheelDeltaX, wheelDeltaY,
1007
+ newX, newY,
1008
+ that = this;
1009
+
1010
+ // Execute the scrollEnd event after 400ms the wheel stopped scrolling
1011
+ clearTimeout(this.wheelTimeout);
1012
+ this.wheelTimeout = setTimeout(function () {
1013
+ that._execEvent('scrollEnd');
1014
+ }, 400);
1015
+
1016
+ e.preventDefault();
1017
+ e.stopPropagation();
1018
+
1019
+ if ( 'deltaX' in e ) {
1020
+ wheelDeltaX = -e.deltaX;
1021
+ wheelDeltaY = -e.deltaY;
1022
+
1023
+ // Checke whether deltaMode is DOM_DELTA_LINE
1024
+ if (e.deltaMode === 1) {
1025
+ wheelDeltaX = wheelDeltaX / 3 * this.options.mouseWheelSpeed;
1026
+ wheelDeltaY = wheelDeltaY / 3 * this.options.mouseWheelSpeed;
1027
+ }
1028
+ } else if ( 'wheelDeltaX' in e ) {
1029
+ wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
1030
+ wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
1031
+ } else if ( 'wheelDelta' in e ) {
1032
+ wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
1033
+ } else if ( 'detail' in e ) {
1034
+ wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
1035
+ } else {
1036
+ return;
1037
+ }
1038
+
1039
+ wheelDeltaX *= this.options.invertWheelDirection;
1040
+ wheelDeltaY *= this.options.invertWheelDirection;
1041
+
1042
+ if ( !this.hasVerticalScroll && !this.options.noMouseWheelScrollX) {
1043
+ wheelDeltaX = wheelDeltaY;
1044
+ }
1045
+
1046
+ newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
1047
+ newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
1048
+
1049
+ if ( newX > 0 ) {
1050
+ newX = 0;
1051
+ } else if ( newX < this.maxScrollX ) {
1052
+ newX = this.maxScrollX;
1053
+ }
1054
+
1055
+ if ( newY > 0 ) {
1056
+ newY = 0;
1057
+
1058
+ } else if ( newY < this.maxScrollY ) {
1059
+ newY = this.maxScrollY;
1060
+ }
1061
+
1062
+ this.scrollTo(newX, newY, 0);
1063
+
1064
+ if ( this.options.probeType > 1 ) {
1065
+ this._execEvent('scroll');
1066
+ }
1067
+
1068
+ this._execEvent(wheelDeltaY > 0 ? 'mousewheelup' : 'mousewheeldown'); // CS
1069
+ // INSERT POINT: _wheel
1070
+ },
1071
+
1072
+ _initSnap: function () {
1073
+ this.currentPage = {};
1074
+
1075
+ if ( typeof this.options.snap == 'string' ) {
1076
+ this.options.snap = this.scroller.querySelectorAll(this.options.snap);
1077
+ }
1078
+
1079
+ this.on('refresh', function () {
1080
+ var i = 0, l,
1081
+ m = 0, n,
1082
+ cx, cy,
1083
+ x = 0, y,
1084
+ stepX = this.options.snapStepX || this.wrapperWidth,
1085
+ stepY = this.options.snapStepY || this.wrapperHeight,
1086
+ el;
1087
+
1088
+ this.pages = [];
1089
+
1090
+ if ( this.options.snap === true ) {
1091
+ cx = Math.round( stepX / 2 );
1092
+ cy = Math.round( stepY / 2 );
1093
+
1094
+ while ( x > -this.scrollerWidth ) {
1095
+ this.pages[i] = [];
1096
+ l = 0;
1097
+ y = 0;
1098
+
1099
+ while ( y > -this.scrollerHeight ) {
1100
+ this.pages[i][l] = {
1101
+ x: Math.max(x, this.maxScrollX),
1102
+ y: Math.max(y, this.maxScrollY),
1103
+ width: stepX,
1104
+ height: stepY,
1105
+ cx: x - cx,
1106
+ cy: y - cy
1107
+ };
1108
+
1109
+ y -= stepY;
1110
+ l++;
1111
+ }
1112
+
1113
+ x -= stepX;
1114
+ i++;
1115
+ }
1116
+ } else {
1117
+ el = this.options.snap;
1118
+ l = el.length;
1119
+ n = -1;
1120
+
1121
+ for ( ; i < l; i++ ) {
1122
+ if ( i === 0 || this.offsetX(el[i]) <= this.offsetX(el[i-1]) ) {
1123
+ m = 0;
1124
+ n++;
1125
+ }
1126
+
1127
+ if ( !this.pages[m] ) {
1128
+ this.pages[m] = [];
1129
+ }
1130
+
1131
+ x = Math.max(-this.offsetX(el[i]), this.maxScrollX);
1132
+ y = Math.max(-el[i].offsetTop, this.maxScrollY);
1133
+ cx = x - Math.round(el[i].offsetWidth / 2);
1134
+ cy = y - Math.round(el[i].offsetHeight / 2);
1135
+
1136
+ this.pages[m][n] = {
1137
+ x: x,
1138
+ y: y,
1139
+ width: el[i].offsetWidth,
1140
+ height: el[i].offsetHeight,
1141
+ cx: cx,
1142
+ cy: cy
1143
+ };
1144
+
1145
+ if ( x > this.maxScrollX ) {
1146
+ m++;
1147
+ }
1148
+ }
1149
+ }
1150
+
1151
+ this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
1152
+
1153
+ // Update snap threshold if needed
1154
+ if ( this.options.snapThreshold % 1 === 0 ) {
1155
+ this.snapThresholdX = this.options.snapThreshold;
1156
+ this.snapThresholdY = this.options.snapThreshold;
1157
+ } else {
1158
+ this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
1159
+ this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
1160
+ }
1161
+ });
1162
+
1163
+ this.on('flick', function () {
1164
+ var time = this.options.snapSpeed || Math.max(
1165
+ Math.max(
1166
+ Math.min(Math.abs(this.x - this.startX), 1000),
1167
+ Math.min(Math.abs(this.y - this.startY), 1000)
1168
+ ), 300);
1169
+
1170
+ this.goToPage(
1171
+ this.currentPage.pageX + this.directionX,
1172
+ this.currentPage.pageY + this.directionY,
1173
+ time
1174
+ );
1175
+ });
1176
+ },
1177
+
1178
+ _nearestSnap: function (x, y) {
1179
+ var i = 0,
1180
+ l = this.pages.length,
1181
+ m = 0;
1182
+
1183
+ // Check if we exceeded the snap threshold
1184
+ if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
1185
+ Math.abs(y - this.absStartY) < this.snapThresholdY ) {
1186
+ return this.currentPage;
1187
+ }
1188
+
1189
+ if ( x > 0 ) {
1190
+ x = 0;
1191
+ } else if ( x < this.maxScrollX ) {
1192
+ x = this.maxScrollX;
1193
+ }
1194
+
1195
+ if ( y > 0 ) {
1196
+ y = 0;
1197
+ } else if ( y < this.maxScrollY ) {
1198
+ y = this.maxScrollY;
1199
+ }
1200
+
1201
+ for ( ; i < l; i++ ) {
1202
+ if ( x >= this.pages[i][0].cx ) {
1203
+ x = this.pages[i][0].x;
1204
+ break;
1205
+ }
1206
+ }
1207
+
1208
+ l = this.pages[i].length;
1209
+
1210
+ for ( ; m < l; m++ ) {
1211
+ if ( y >= this.pages[0][m].cy ) {
1212
+ y = this.pages[0][m].y;
1213
+ break;
1214
+ }
1215
+ }
1216
+
1217
+ if ( i == this.currentPage.pageX ) {
1218
+ i += this.directionX;
1219
+
1220
+ if ( i < 0 ) {
1221
+ i = 0;
1222
+ } else if ( i >= this.pages.length ) {
1223
+ i = this.pages.length - 1;
1224
+ }
1225
+
1226
+ x = this.pages[i][0].x;
1227
+ }
1228
+
1229
+ if ( m == this.currentPage.pageY ) {
1230
+ m += this.directionY;
1231
+
1232
+ if ( m < 0 ) {
1233
+ m = 0;
1234
+ } else if ( m >= this.pages[0].length ) {
1235
+ m = this.pages[0].length - 1;
1236
+ }
1237
+
1238
+ y = this.pages[0][m].y;
1239
+ }
1240
+
1241
+ return {
1242
+ x: x,
1243
+ y: y,
1244
+ pageX: i,
1245
+ pageY: m
1246
+ };
1247
+ },
1248
+
1249
+ goToPage: function (x, y, time, easing) {
1250
+ easing = easing || this.options.bounceEasing;
1251
+
1252
+ if ( x >= this.pages.length ) {
1253
+ x = this.pages.length - 1;
1254
+ } else if ( x < 0 ) {
1255
+ x = 0;
1256
+ }
1257
+
1258
+ if ( y >= this.pages[0].length ) {
1259
+ y = this.pages[0].length - 1;
1260
+ } else if ( y < 0 ) {
1261
+ y = 0;
1262
+ }
1263
+
1264
+ var posX = this.pages[x][y].x,
1265
+ posY = this.pages[x][y].y;
1266
+
1267
+ time = time === undefined ? this.options.snapSpeed || Math.max(
1268
+ Math.max(
1269
+ Math.min(Math.abs(posX - this.x), 1000),
1270
+ Math.min(Math.abs(posY - this.y), 1000)
1271
+ ), 300) : time;
1272
+
1273
+ this.currentPage = {
1274
+ x: posX,
1275
+ y: posY,
1276
+ pageX: x,
1277
+ pageY: y
1278
+ };
1279
+
1280
+ this.scrollTo(posX, posY, time, easing);
1281
+ },
1282
+
1283
+ next: function (time, easing) {
1284
+ var x = this.currentPage.pageX,
1285
+ y = this.currentPage.pageY;
1286
+
1287
+ x++;
1288
+
1289
+ if ( x >= this.pages.length && this.hasVerticalScroll ) {
1290
+ x = 0;
1291
+ y++;
1292
+ }
1293
+
1294
+ this.goToPage(x, y, time, easing);
1295
+ },
1296
+
1297
+ prev: function (time, easing) {
1298
+ var x = this.currentPage.pageX,
1299
+ y = this.currentPage.pageY;
1300
+
1301
+ x--;
1302
+
1303
+ if ( x < 0 && this.hasVerticalScroll ) {
1304
+ x = 0;
1305
+ y--;
1306
+ }
1307
+
1308
+ this.goToPage(x, y, time, easing);
1309
+ },
1310
+
1311
+ _initKeys: function (e) {
1312
+ // default key bindings
1313
+ var keys = {
1314
+ pageUp: 33,
1315
+ pageDown: 34,
1316
+ end: 35,
1317
+ home: 36,
1318
+ left: 37,
1319
+ up: 38,
1320
+ right: 39,
1321
+ down: 40
1322
+ };
1323
+ var i;
1324
+
1325
+ // if you give me characters I give you keycode
1326
+ if ( typeof this.options.keyBindings == 'object' ) {
1327
+ for ( i in this.options.keyBindings ) {
1328
+ if ( typeof this.options.keyBindings[i] == 'string' ) {
1329
+ this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);
1330
+ }
1331
+ }
1332
+ } else {
1333
+ this.options.keyBindings = {};
1334
+ }
1335
+
1336
+ for ( i in keys ) {
1337
+ this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
1338
+ }
1339
+
1340
+ utils.addEvent(window, 'keydown', this);
1341
+
1342
+ this.on('destroy', function () {
1343
+ utils.removeEvent(window, 'keydown', this);
1344
+ });
1345
+ },
1346
+
1347
+ _key: function (e) {
1348
+ var keyboardEvent = null;
1349
+
1350
+ if ( !this.enabled ) {
1351
+ return;
1352
+ }
1353
+
1354
+ var snap = this.options.snap, // we are using this alot, better to cache it
1355
+ newX = snap ? this.currentPage.pageX : this.x,
1356
+ newY = snap ? this.currentPage.pageY : this.y,
1357
+ now = utils.getTime(),
1358
+ prevTime = this.keyTime || 0,
1359
+ acceleration = 0.250,
1360
+ pos;
1361
+
1362
+ if ( this.options.useTransition && this.isInTransition ) {
1363
+ pos = this.getComputedPosition();
1364
+
1365
+ this._translate(Math.round(pos.x), Math.round(pos.y));
1366
+ this.isInTransition = false;
1367
+ }
1368
+
1369
+ this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
1370
+
1371
+ switch ( e.keyCode ) {
1372
+ case this.options.keyBindings.pageUp:
1373
+ if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
1374
+ newX += snap ? 1 : this.wrapperWidth;
1375
+ } else {
1376
+ newY += snap ? 1 : this.wrapperHeight;
1377
+ keyboardEvent = 'keyboardup'; // CS
1378
+ }
1379
+ break;
1380
+ case this.options.keyBindings.pageDown:
1381
+ if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
1382
+ newX -= snap ? 1 : this.wrapperWidth;
1383
+ } else {
1384
+ newY -= snap ? 1 : this.wrapperHeight;
1385
+ keyboardEvent = 'keyboarddown'; // CS
1386
+ }
1387
+ break;
1388
+ case this.options.keyBindings.end:
1389
+ newX = snap ? this.pages.length-1 : this.maxScrollX;
1390
+ newY = snap ? this.pages[0].length-1 : this.maxScrollY;
1391
+ keyboardEvent = 'keyboardhintdown'; // CS
1392
+ break;
1393
+ case this.options.keyBindings.home:
1394
+ newX = 0;
1395
+ newY = 0;
1396
+ keyboardEvent = 'keyboardhintup'; // CS
1397
+ break;
1398
+ case this.options.keyBindings.left:
1399
+ newX += snap ? -1 : 5 + this.keyAcceleration>>0;
1400
+ break;
1401
+ case this.options.keyBindings.up:
1402
+ newY += snap ? 1 : 5 + this.keyAcceleration>>0;
1403
+ keyboardEvent = 'keyboardup'; // CS
1404
+ break;
1405
+ case this.options.keyBindings.right:
1406
+ newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
1407
+ break;
1408
+ case this.options.keyBindings.down:
1409
+ newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
1410
+ keyboardEvent = 'keyboarddown'; // CS
1411
+ break;
1412
+ }
1413
+
1414
+ if ( snap ) {
1415
+ this.goToPage(newX, newY);
1416
+ return;
1417
+ }
1418
+
1419
+ if ( newX > 0 ) {
1420
+ newX = 0;
1421
+ this.keyAcceleration = 0;
1422
+ } else if ( newX < this.maxScrollX ) {
1423
+ newX = this.maxScrollX;
1424
+ this.keyAcceleration = 0;
1425
+ }
1426
+
1427
+ if ( newY > 0 ) {
1428
+ newY = 0;
1429
+ this.keyAcceleration = 0;
1430
+ } else if ( newY < this.maxScrollY ) {
1431
+ newY = this.maxScrollY;
1432
+ this.keyAcceleration = 0;
1433
+ }
1434
+
1435
+ if (keyboardEvent) { this._execEvent(keyboardEvent, e); } // CS
1436
+
1437
+ this.scrollTo(newX, newY, 0);
1438
+
1439
+ this.keyTime = now;
1440
+
1441
+ if (this.enabled) { this._execEvent('afterkeyboard'); } // CS
1442
+ },
1443
+
1444
+ _animate: function (destX, destY, duration, easingFn) {
1445
+ var that = this,
1446
+ startX = this.x,
1447
+ startY = this.y,
1448
+ startTime = utils.getTime(),
1449
+ destTime = startTime + duration;
1450
+
1451
+ function step () {
1452
+ var now = utils.getTime(),
1453
+ newX, newY,
1454
+ easing;
1455
+
1456
+ if ( now >= destTime ) {
1457
+ that.isAnimating = false;
1458
+ that._translate(destX, destY);
1459
+
1460
+ if ( !that.resetPosition(that.options.bounceTime) ) {
1461
+ that._execEvent('scrollEnd');
1462
+ }
1463
+
1464
+ return;
1465
+ }
1466
+
1467
+ now = ( now - startTime ) / duration;
1468
+ easing = easingFn(now);
1469
+ newX = ( destX - startX ) * easing + startX;
1470
+ newY = ( destY - startY ) * easing + startY;
1471
+ that._translate(newX, newY);
1472
+
1473
+ if ( that.isAnimating ) {
1474
+ rAF(step);
1475
+ }
1476
+
1477
+ if ( that.options.probeType == 3 ) {
1478
+ that._execEvent('scroll');
1479
+ }
1480
+ }
1481
+
1482
+ this.isAnimating = true;
1483
+ step();
1484
+ },
1485
+
1486
+ handleEvent: function (e) {
1487
+ switch ( e.type ) {
1488
+ case 'touchstart':
1489
+ case 'MSPointerDown':
1490
+ case 'mousedown':
1491
+ this._start(e);
1492
+ break;
1493
+ case 'touchmove':
1494
+ case 'MSPointerMove':
1495
+ case 'mousemove':
1496
+ this._move(e);
1497
+ break;
1498
+ case 'touchend':
1499
+ case 'MSPointerUp':
1500
+ case 'mouseup':
1501
+ case 'touchcancel':
1502
+ case 'MSPointerCancel':
1503
+ case 'mousecancel':
1504
+ this._end(e);
1505
+ break;
1506
+ case 'orientationchange':
1507
+ case 'resize':
1508
+ this._resize();
1509
+ break;
1510
+ case 'transitionend':
1511
+ case 'webkitTransitionEnd':
1512
+ case 'oTransitionEnd':
1513
+ case 'MSTransitionEnd':
1514
+ this._transitionEnd(e);
1515
+ break;
1516
+ case 'wheel':
1517
+ case 'DOMMouseScroll':
1518
+ case 'mousewheel':
1519
+ this._wheel(e);
1520
+ break;
1521
+ case 'keydown':
1522
+ this._key(e);
1523
+ break;
1524
+ }
1525
+ }
1526
+ };
1527
+ function createDefaultScrollbar (direction, interactive, type) {
1528
+ var scrollbar = document.createElement('div'),
1529
+ indicator = document.createElement('div');
1530
+
1531
+ if ( type === true ) {
1532
+ scrollbar.style.cssText = 'position:absolute;z-index:9999';
1533
+ indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';
1534
+ }
1535
+
1536
+ indicator.className = 'iScrollIndicator';
1537
+
1538
+ if ( direction == 'h' ) {
1539
+ if ( type === true ) {
1540
+ scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
1541
+ indicator.style.height = '100%';
1542
+ }
1543
+ scrollbar.className = 'iScrollHorizontalScrollbar';
1544
+ } else {
1545
+ if ( type === true ) {
1546
+ scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
1547
+ indicator.style.width = '100%';
1548
+ }
1549
+ scrollbar.className = 'iScrollVerticalScrollbar';
1550
+ }
1551
+
1552
+ if ( !interactive ) {
1553
+ scrollbar.style.pointerEvents = 'none';
1554
+ }
1555
+
1556
+ scrollbar.appendChild(indicator);
1557
+
1558
+ return scrollbar;
1559
+ }
1560
+
1561
+ function Indicator (scroller, options) {
1562
+ this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
1563
+ this.indicator = this.wrapper.children[0];
1564
+ this.indicatorStyle = this.indicator.style;
1565
+ this.scroller = scroller;
1566
+
1567
+ this.options = {
1568
+ listenX: true,
1569
+ listenY: true,
1570
+ interactive: false,
1571
+ resize: true,
1572
+ defaultScrollbars: false,
1573
+ speedRatioX: 0,
1574
+ speedRatioY: 0
1575
+ };
1576
+
1577
+ for ( var i in options ) {
1578
+ this.options[i] = options[i];
1579
+ }
1580
+
1581
+ this.sizeRatioX = 1;
1582
+ this.sizeRatioY = 1;
1583
+ this.maxPosX = 0;
1584
+ this.maxPosY = 0;
1585
+
1586
+ if ( this.options.interactive ) {
1587
+ utils.addEvent(this.indicator, 'touchstart', this);
1588
+ utils.addEvent(this.indicator, 'MSPointerDown', this);
1589
+ utils.addEvent(this.indicator, 'mousedown', this);
1590
+
1591
+ utils.addEvent(window, 'touchend', this);
1592
+ utils.addEvent(window, 'MSPointerUp', this);
1593
+ utils.addEvent(window, 'mouseup', this);
1594
+ }
1595
+ }
1596
+
1597
+ Indicator.prototype = {
1598
+ handleEvent: function (e) {
1599
+ switch ( e.type ) {
1600
+ case 'touchstart':
1601
+ case 'MSPointerDown':
1602
+ case 'mousedown':
1603
+ this._start(e);
1604
+ break;
1605
+ case 'touchmove':
1606
+ case 'MSPointerMove':
1607
+ case 'mousemove':
1608
+ this._move(e);
1609
+ break;
1610
+ case 'touchend':
1611
+ case 'MSPointerUp':
1612
+ case 'mouseup':
1613
+ case 'touchcancel':
1614
+ case 'MSPointerCancel':
1615
+ case 'mousecancel':
1616
+ this._end(e);
1617
+ break;
1618
+ }
1619
+ },
1620
+
1621
+ destroy: function () {
1622
+ if ( this.options.interactive ) {
1623
+ utils.removeEvent(this.indicator, 'touchstart', this);
1624
+ utils.removeEvent(this.indicator, 'MSPointerDown', this);
1625
+ utils.removeEvent(this.indicator, 'mousedown', this);
1626
+
1627
+ utils.removeEvent(window, 'touchmove', this);
1628
+ utils.removeEvent(window, 'MSPointerMove', this);
1629
+ utils.removeEvent(window, 'mousemove', this);
1630
+
1631
+ utils.removeEvent(window, 'touchend', this);
1632
+ utils.removeEvent(window, 'MSPointerUp', this);
1633
+ utils.removeEvent(window, 'mouseup', this);
1634
+ }
1635
+
1636
+ if ( this.options.defaultScrollbars ) {
1637
+ this.wrapper.parentNode.removeChild(this.wrapper);
1638
+ }
1639
+ },
1640
+
1641
+ _start: function (e) {
1642
+ var point = e.touches ? e.touches[0] : e;
1643
+
1644
+ e.preventDefault();
1645
+ e.stopPropagation();
1646
+
1647
+ this.transitionTime(0);
1648
+
1649
+ this.initiated = true;
1650
+ this.moved = false;
1651
+ this.lastPointX = point.pageX;
1652
+ this.lastPointY = point.pageY;
1653
+
1654
+ this.startTime = utils.getTime();
1655
+
1656
+ utils.addEvent(window, 'touchmove', this);
1657
+ utils.addEvent(window, 'MSPointerMove', this);
1658
+ utils.addEvent(window, 'mousemove', this);
1659
+
1660
+ this.scroller._execEvent('scrollStart');
1661
+ },
1662
+
1663
+ _move: function (e) {
1664
+ var point = e.touches ? e.touches[0] : e,
1665
+ deltaX, deltaY,
1666
+ newX, newY,
1667
+ timestamp = utils.getTime();
1668
+
1669
+ this.moved = true;
1670
+
1671
+ deltaX = point.pageX - this.lastPointX;
1672
+ this.lastPointX = point.pageX;
1673
+
1674
+ deltaY = point.pageY - this.lastPointY;
1675
+ this.lastPointY = point.pageY;
1676
+
1677
+ newX = this.x + deltaX;
1678
+ newY = this.y + deltaY;
1679
+
1680
+ this._pos(newX, newY);
1681
+
1682
+ e.preventDefault();
1683
+ e.stopPropagation();
1684
+ },
1685
+
1686
+ _end: function (e) {
1687
+ if ( !this.initiated ) {
1688
+ return;
1689
+ }
1690
+
1691
+ this.initiated = false;
1692
+
1693
+ e.preventDefault();
1694
+ e.stopPropagation();
1695
+
1696
+ utils.removeEvent(window, 'touchmove', this);
1697
+ utils.removeEvent(window, 'MSPointerMove', this);
1698
+ utils.removeEvent(window, 'mousemove', this);
1699
+
1700
+ if ( this.moved ) {
1701
+ this.scroller._execEvent('scrollEnd');
1702
+ }
1703
+ },
1704
+
1705
+ transitionTime: function (time) {
1706
+ time = time || 0;
1707
+ this.indicatorStyle[utils.style.transitionDuration] = time + 'ms';
1708
+ },
1709
+
1710
+ transitionTimingFunction: function (easing) {
1711
+ this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
1712
+ },
1713
+
1714
+ refresh: function () {
1715
+ this.transitionTime(0);
1716
+
1717
+ if ( this.options.listenX && !this.options.listenY ) {
1718
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
1719
+ } else if ( this.options.listenY && !this.options.listenX ) {
1720
+ this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
1721
+ } else {
1722
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
1723
+ }
1724
+
1725
+ if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
1726
+ utils.addClass(this.wrapper, 'iScrollBothScrollbars');
1727
+ utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
1728
+
1729
+ if ( this.options.defaultScrollbars && this.options.customStyle ) {
1730
+ if ( this.options.listenX ) {
1731
+ this.wrapper.style.right = '8px';
1732
+ } else {
1733
+ this.wrapper.style.bottom = '8px';
1734
+ }
1735
+ }
1736
+ } else {
1737
+ utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
1738
+ utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
1739
+
1740
+ if ( this.options.defaultScrollbars && this.options.customStyle ) {
1741
+ if ( this.options.listenX ) {
1742
+ this.wrapper.style.right = '2px';
1743
+ } else {
1744
+ this.wrapper.style.bottom = '2px';
1745
+ }
1746
+ }
1747
+ }
1748
+
1749
+ var r = this.wrapper.offsetHeight; // force refresh
1750
+
1751
+ if ( this.options.listenX ) {
1752
+ this.wrapperWidth = this.wrapper.clientWidth;
1753
+ if ( this.options.resize ) {
1754
+ this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / this.scroller.scrollerWidth), 8);
1755
+ this.indicatorStyle.width = this.indicatorWidth + 'px';
1756
+ } else {
1757
+ this.indicatorWidth = this.indicator.clientWidth;
1758
+ }
1759
+ this.maxPosX = this.wrapperWidth - this.indicatorWidth;
1760
+ this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
1761
+ }
1762
+
1763
+ if ( this.options.listenY ) {
1764
+ this.wrapperHeight = this.wrapper.clientHeight;
1765
+ if ( this.options.resize ) {
1766
+ this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / this.scroller.scrollerHeight), 8);
1767
+ this.indicatorStyle.height = this.indicatorHeight + 'px';
1768
+ } else {
1769
+ this.indicatorHeight = this.indicator.clientHeight;
1770
+ }
1771
+
1772
+ this.maxPosY = this.wrapperHeight - this.indicatorHeight;
1773
+ this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
1774
+ }
1775
+
1776
+ this.updatePosition();
1777
+ },
1778
+
1779
+ updatePosition: function () {
1780
+ var x = Math.round(this.sizeRatioX * this.scroller.x) || 0,
1781
+ y = Math.round(this.sizeRatioY * this.scroller.y) || 0;
1782
+
1783
+ if ( !this.options.ignoreBoundaries ) {
1784
+ if ( x < 0 ) {
1785
+ x = 0;
1786
+ } else if ( x > this.maxPosX ) {
1787
+ x = this.maxPosX;
1788
+ }
1789
+
1790
+ if ( y < 0 ) {
1791
+ y = 0;
1792
+ } else if ( y > this.maxPosY ) {
1793
+ y = this.maxPosY;
1794
+ }
1795
+ }
1796
+
1797
+ this.x = x;
1798
+ this.y = y;
1799
+
1800
+ if ( this.scroller.options.useTransform ) {
1801
+ this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
1802
+ } else {
1803
+ this.indicatorStyle.left = x + 'px';
1804
+ this.indicatorStyle.top = y + 'px';
1805
+ }
1806
+ },
1807
+
1808
+ _pos: function (x, y) {
1809
+ if ( x < 0 ) {
1810
+ x = 0;
1811
+ } else if ( x > this.maxPosX ) {
1812
+ x = this.maxPosX;
1813
+ }
1814
+
1815
+ if ( y < 0 ) {
1816
+ y = 0;
1817
+ } else if ( y > this.maxPosY ) {
1818
+ y = this.maxPosY;
1819
+ }
1820
+
1821
+ x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
1822
+ y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
1823
+
1824
+ this.scroller.scrollTo(x, y);
1825
+ }
1826
+ };
1827
+
1828
+ IScroll.ease = utils.ease;
1829
+
1830
+ return IScroll;
1831
+
1832
+ })(window, document, Math);
1833
+
1834
+ module.exports = IScroll;