bm-core-ui 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/CHANGELOG.md +1624 -0
  2. package/LICENSE +21 -0
  3. package/README.md +145 -0
  4. package/build/@types/index.d.ts +14078 -0
  5. package/build/BMCodeEditor/BMCodeEditor.js +707 -0
  6. package/build/BMCollectionView/BMCollectionView.js +5861 -0
  7. package/build/BMCollectionView/BMCollectionViewCell.js +688 -0
  8. package/build/BMCollectionView/BMCollectionViewFlowLayout.js +4467 -0
  9. package/build/BMCollectionView/BMCollectionViewLayout.js +830 -0
  10. package/build/BMCollectionView/BMCollectionViewLayoutAttributes.js +673 -0
  11. package/build/BMCollectionView/BMCollectionViewMasonryLayout.js +491 -0
  12. package/build/BMCollectionView/BMCollectionViewStackLayout.js +634 -0
  13. package/build/BMCollectionView/BMCollectionViewTileLayout.js +1121 -0
  14. package/build/BMCoreUI.css +2833 -0
  15. package/build/BMView/BMAttributedLabelView.js +310 -0
  16. package/build/BMView/BMLayoutConstraint_v2.5.js +1813 -0
  17. package/build/BMView/BMLayoutGuide.js +192 -0
  18. package/build/BMView/BMLayoutSizeClass.js +466 -0
  19. package/build/BMView/BMMenu.js +574 -0
  20. package/build/BMView/BMScrollView.js +247 -0
  21. package/build/BMView/BMTextField.js +512 -0
  22. package/build/BMView/BMTextFieldDelegate.js +71 -0
  23. package/build/BMView/BMView_v2.5.js +3572 -0
  24. package/build/BMView/BMViewport.js +221 -0
  25. package/build/BMViewLayoutEditor/BMLayoutEditor.js +6117 -0
  26. package/build/BMViewLayoutEditor/BMLayoutEditorConstraintSettings.js +417 -0
  27. package/build/BMViewLayoutEditor/BMLayoutEditorDelegate.js +59 -0
  28. package/build/BMViewLayoutEditor/BMLayoutEditorSettingCells.js +1653 -0
  29. package/build/BMViewLayoutEditor/BMLayoutEditorSettings.js +1480 -0
  30. package/build/BMViewLayoutEditor/BMLayoutEditorSettingsComplexCells.js +431 -0
  31. package/build/BMViewLayoutEditor/BMLayoutEditorSettingsDelegate.js +46 -0
  32. package/build/BMViewLayoutEditor/BMLayoutEditorVariablesController.js +460 -0
  33. package/build/BMViewLayoutEditor/BMLayoutEditorViewGroupSettings.js +293 -0
  34. package/build/BMViewLayoutEditor/BMLayoutEditorViewSettings.js +382 -0
  35. package/build/BMViewLayoutEditor/BMLayoutVariableProvider.js +202 -0
  36. package/build/BMWindow/BMConfirmationPopup.js +477 -0
  37. package/build/BMWindow/BMKeyboardShortcut.js +151 -0
  38. package/build/BMWindow/BMPopover/BMPopover.js +492 -0
  39. package/build/BMWindow/BMToolWindow.js +71 -0
  40. package/build/BMWindow/BMWindow.js +2000 -0
  41. package/build/Core/BMAnimationContext.js +1181 -0
  42. package/build/Core/BMColor.js +991 -0
  43. package/build/Core/BMCoreUI.js +470 -0
  44. package/build/Core/BMFunctionCollection.js +110 -0
  45. package/build/Core/BMIndexPath.js +165 -0
  46. package/build/Core/BMInset.js +138 -0
  47. package/build/Core/BMKeyPath.js +100 -0
  48. package/build/Core/BMPoint.js +291 -0
  49. package/build/Core/BMRect.js +556 -0
  50. package/build/Core/BMSize.js +137 -0
  51. package/build/iScroll/LICENSE +22 -0
  52. package/build/iScroll/iscroll-probe.js +2154 -0
  53. package/build/images/AlignBottom.png +0 -0
  54. package/build/images/AlignCenterX.png +0 -0
  55. package/build/images/AlignCenterY.png +0 -0
  56. package/build/images/AlignLeading.png +0 -0
  57. package/build/images/AlignTop.png +0 -0
  58. package/build/images/AlignTrailing.png +0 -0
  59. package/build/images/AllConstraints.png +0 -0
  60. package/build/images/BottomConstraint.png +0 -0
  61. package/build/images/CenterXConstraint.png +0 -0
  62. package/build/images/CenterYConstraint.png +0 -0
  63. package/build/images/CoreUI2.png +0 -0
  64. package/build/images/CoreUI2@2x.png +0 -0
  65. package/build/images/Desktop.png +0 -0
  66. package/build/images/DesktopMini.png +0 -0
  67. package/build/images/EqualHeight.png +0 -0
  68. package/build/images/EqualHorizontalSpacing.png +0 -0
  69. package/build/images/EqualHorizontalSpacingInSuperview.png +0 -0
  70. package/build/images/EqualVerticalSpacing.png +0 -0
  71. package/build/images/EqualVerticalSpacingInSuperview.png +0 -0
  72. package/build/images/EqualWidth.png +0 -0
  73. package/build/images/HeightConstraint.png +0 -0
  74. package/build/images/InactiveConstraints.png +0 -0
  75. package/build/images/Layout.png +0 -0
  76. package/build/images/LayoutVariables.png +0 -0
  77. package/build/images/LeftConstraint.png +0 -0
  78. package/build/images/OwnConstraints.png +0 -0
  79. package/build/images/Phone.png +0 -0
  80. package/build/images/PhoneLandscape.png +0 -0
  81. package/build/images/PhoneLandscapeMini.png +0 -0
  82. package/build/images/PhoneMini.png +0 -0
  83. package/build/images/PhonePortrait.png +0 -0
  84. package/build/images/PhonePortraitMini.png +0 -0
  85. package/build/images/Properties.png +0 -0
  86. package/build/images/RightConstraint.png +0 -0
  87. package/build/images/SubviewConstraints.png +0 -0
  88. package/build/images/Tablet.png +0 -0
  89. package/build/images/TabletLandscape.png +0 -0
  90. package/build/images/TabletLandscapeMini.png +0 -0
  91. package/build/images/TabletMini.png +0 -0
  92. package/build/images/TabletPortrait.png +0 -0
  93. package/build/images/TabletPortraitMini.png +0 -0
  94. package/build/images/TopConstraint.png +0 -0
  95. package/build/images/WidthConstraint.png +0 -0
  96. package/build/index.js +40 -0
  97. package/lib/@types/BMCoreUI.min.d.ts +14078 -0
  98. package/lib/BMCoreUI.min.js +1 -0
  99. package/package.json +58 -0
@@ -0,0 +1,2154 @@
1
+ /*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ @license: http://cubiq.org/license */
2
+ export var IScroll = (function (window, document, Math) {
3
+ var rAF = window.requestAnimationFrame ||
4
+ window.webkitRequestAnimationFrame ||
5
+ window.mozRequestAnimationFrame ||
6
+ window.oRequestAnimationFrame ||
7
+ window.msRequestAnimationFrame ||
8
+ function (callback) { window.setTimeout(callback, 1000 / 60); };
9
+
10
+ var utils = (function () {
11
+ var me = {};
12
+
13
+ var _elementStyle = document.createElement('div').style;
14
+ var _vendor = (function () {
15
+ var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
16
+ transform,
17
+ i = 0,
18
+ l = vendors.length;
19
+
20
+ for ( ; i < l; i++ ) {
21
+ transform = vendors[i] + 'ransform';
22
+ if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
23
+ }
24
+
25
+ return false;
26
+ })();
27
+
28
+ function _prefixStyle (style) {
29
+ if ( _vendor === false ) return false;
30
+ if ( _vendor === '' ) return style;
31
+ return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
32
+ }
33
+
34
+ me.getTime = Date.now || function getTime () { return new Date().getTime(); };
35
+
36
+ me.extend = function (target, obj) {
37
+ for ( var i in obj ) {
38
+ target[i] = obj[i];
39
+ }
40
+ };
41
+
42
+ me.addEvent = function (el, type, fn, capture) {
43
+ el.addEventListener(type, fn, !!capture);
44
+ };
45
+
46
+ me.removeEvent = function (el, type, fn, capture) {
47
+ el.removeEventListener(type, fn, !!capture);
48
+ };
49
+
50
+ me.prefixPointerEvent = function (pointerEvent) {
51
+ return window.MSPointerEvent ?
52
+ 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
53
+ pointerEvent;
54
+ };
55
+
56
+ me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
57
+ var distance = current - start,
58
+ speed = Math.abs(distance) / time,
59
+ destination,
60
+ duration;
61
+
62
+ deceleration = deceleration === undefined ? 0.0006 : deceleration;
63
+
64
+ destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
65
+ duration = speed / deceleration;
66
+
67
+ if ( destination < lowerMargin ) {
68
+ destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
69
+ distance = Math.abs(destination - current);
70
+ duration = distance / speed;
71
+ } else if ( destination > 0 ) {
72
+ destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
73
+ distance = Math.abs(current) + destination;
74
+ duration = distance / speed;
75
+ }
76
+
77
+ return {
78
+ destination: Math.round(destination),
79
+ duration: duration
80
+ };
81
+ };
82
+
83
+ var _transform = _prefixStyle('transform');
84
+
85
+ me.extend(me, {
86
+ hasTransform: _transform !== false,
87
+ hasPerspective: _prefixStyle('perspective') in _elementStyle,
88
+ hasTouch: 'ontouchstart' in window,
89
+ hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
90
+ hasTransition: _prefixStyle('transition') in _elementStyle
91
+ });
92
+
93
+ /*
94
+ This should find all Android browsers lower than build 535.19 (both stock browser and webview)
95
+ - galaxy S2 is ok
96
+ - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
97
+ - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
98
+ - galaxy S3 is badAndroid (stock brower, webview)
99
+ `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
100
+ - galaxy S4 is badAndroid (stock brower, webview)
101
+ `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
102
+ - galaxy S5 is OK
103
+ `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
104
+ - galaxy S6 is OK
105
+ `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
106
+ */
107
+ me.isBadAndroid = (function() {
108
+ var appVersion = window.navigator.appVersion;
109
+ // Android browser is not a chrome browser.
110
+ if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
111
+ var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
112
+ if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
113
+ return parseFloat(safariVersion[1]) < 535.19;
114
+ } else {
115
+ return true;
116
+ }
117
+ } else {
118
+ return false;
119
+ }
120
+ })();
121
+
122
+ me.extend(me.style = {}, {
123
+ transform: _transform,
124
+ transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
125
+ transitionDuration: _prefixStyle('transitionDuration'),
126
+ transitionDelay: _prefixStyle('transitionDelay'),
127
+ transformOrigin: _prefixStyle('transformOrigin')
128
+ });
129
+
130
+ me.hasClass = function (e, c) {
131
+ var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
132
+ return re.test(e.className);
133
+ };
134
+
135
+ me.addClass = function (e, c) {
136
+ if ( me.hasClass(e, c) ) {
137
+ return;
138
+ }
139
+
140
+ var newclass = e.className.split(' ');
141
+ newclass.push(c);
142
+ e.className = newclass.join(' ');
143
+ };
144
+
145
+ me.removeClass = function (e, c) {
146
+ if ( !me.hasClass(e, c) ) {
147
+ return;
148
+ }
149
+
150
+ var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
151
+ e.className = e.className.replace(re, ' ');
152
+ };
153
+
154
+ me.offset = function (el) {
155
+ var left = -el.offsetLeft,
156
+ top = -el.offsetTop;
157
+
158
+ // jshint -W084
159
+ while (el = el.offsetParent) {
160
+ left -= el.offsetLeft;
161
+ top -= el.offsetTop;
162
+ }
163
+ // jshint +W084
164
+
165
+ return {
166
+ left: left,
167
+ top: top
168
+ };
169
+ };
170
+
171
+ me.preventDefaultException = function (el, exceptions) {
172
+ for ( var i in exceptions ) {
173
+ if ( exceptions[i].test(el[i]) ) {
174
+ return true;
175
+ }
176
+ }
177
+
178
+ return false;
179
+ };
180
+
181
+ me.extend(me.eventType = {}, {
182
+ touchstart: 1,
183
+ touchmove: 1,
184
+ touchend: 1,
185
+
186
+ mousedown: 2,
187
+ mousemove: 2,
188
+ mouseup: 2,
189
+
190
+ pointerdown: 3,
191
+ pointermove: 3,
192
+ pointerup: 3,
193
+
194
+ MSPointerDown: 3,
195
+ MSPointerMove: 3,
196
+ MSPointerUp: 3
197
+ });
198
+
199
+ me.extend(me.ease = {}, {
200
+ quadratic: {
201
+ style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
202
+ fn: function (k) {
203
+ return k * ( 2 - k );
204
+ }
205
+ },
206
+ circular: {
207
+ 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)
208
+ fn: function (k) {
209
+ return Math.sqrt( 1 - ( --k * k ) );
210
+ }
211
+ },
212
+ back: {
213
+ style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
214
+ fn: function (k) {
215
+ var b = 4;
216
+ return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
217
+ }
218
+ },
219
+ bounce: {
220
+ style: '',
221
+ fn: function (k) {
222
+ if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
223
+ return 7.5625 * k * k;
224
+ } else if ( k < ( 2 / 2.75 ) ) {
225
+ return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
226
+ } else if ( k < ( 2.5 / 2.75 ) ) {
227
+ return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
228
+ } else {
229
+ return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
230
+ }
231
+ }
232
+ },
233
+ elastic: {
234
+ style: '',
235
+ fn: function (k) {
236
+ var f = 0.22,
237
+ e = 0.4;
238
+
239
+ if ( k === 0 ) { return 0; }
240
+ if ( k == 1 ) { return 1; }
241
+
242
+ return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
243
+ }
244
+ }
245
+ });
246
+
247
+ me.tap = function (e, eventName) {
248
+ var ev = document.createEvent('Event');
249
+ ev.initEvent(eventName, true, true);
250
+ ev.pageX = e.pageX;
251
+ ev.pageY = e.pageY;
252
+ e.target.dispatchEvent(ev);
253
+ };
254
+
255
+ me.click = function (e) {
256
+ var target = e.target,
257
+ ev;
258
+
259
+ if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
260
+ // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
261
+ // initMouseEvent is deprecated.
262
+ ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
263
+ ev.initEvent('click', true, true);
264
+ ev.view = e.view || window;
265
+ ev.detail = 1;
266
+ ev.screenX = target.screenX || 0;
267
+ ev.screenY = target.screenY || 0;
268
+ ev.clientX = target.clientX || 0;
269
+ ev.clientY = target.clientY || 0;
270
+ ev.ctrlKey = !!e.ctrlKey;
271
+ ev.altKey = !!e.altKey;
272
+ ev.shiftKey = !!e.shiftKey;
273
+ ev.metaKey = !!e.metaKey;
274
+ ev.button = 0;
275
+ ev.relatedTarget = null;
276
+ ev._constructed = true;
277
+ target.dispatchEvent(ev);
278
+ }
279
+ };
280
+
281
+ return me;
282
+ })();
283
+ function IScroll (el, options) {
284
+ this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
285
+ this.scroller = this.wrapper.children[0];
286
+ this.scrollerStyle = this.scroller.style; // cache style for better performance
287
+
288
+ this.options = {
289
+
290
+ resizeScrollbars: true,
291
+
292
+ mouseWheelSpeed: 20,
293
+
294
+ snapThreshold: 0.334,
295
+
296
+ // INSERT POINT: OPTIONS
297
+ disablePointer : !utils.hasPointer,
298
+ disableTouch : utils.hasPointer || !utils.hasTouch,
299
+ disableMouse : utils.hasPointer || utils.hasTouch,
300
+ startX: 0,
301
+ startY: 0,
302
+ scrollY: true,
303
+ directionLockThreshold: 5,
304
+ momentum: true,
305
+
306
+ bounce: true,
307
+ bounceTime: 600,
308
+ bounceEasing: '',
309
+
310
+ preventDefault: true,
311
+ preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },
312
+
313
+ HWCompositing: true,
314
+ useTransition: true,
315
+ useTransform: true,
316
+ bindToWrapper: typeof window.onmousedown === "undefined"
317
+ };
318
+
319
+ for ( var i in options ) {
320
+ this.options[i] = options[i];
321
+ }
322
+
323
+ // Normalize options
324
+ this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
325
+
326
+ this.options.useTransition = utils.hasTransition && this.options.useTransition;
327
+ this.options.useTransform = utils.hasTransform && this.options.useTransform;
328
+
329
+ this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
330
+ this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
331
+
332
+ // If you want eventPassthrough I have to lock one of the axes
333
+ this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
334
+ this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
335
+
336
+ // With eventPassthrough we also need lockDirection mechanism
337
+ this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
338
+ this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
339
+
340
+ this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
341
+
342
+ this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
343
+
344
+ if ( this.options.tap === true ) {
345
+ this.options.tap = 'tap';
346
+ }
347
+
348
+ // https://github.com/cubiq/iscroll/issues/1029
349
+ if (!this.options.useTransition && !this.options.useTransform) {
350
+ if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
351
+ this.scrollerStyle.position = "relative";
352
+ }
353
+ }
354
+
355
+ if ( this.options.shrinkScrollbars == 'scale' ) {
356
+ this.options.useTransition = false;
357
+ }
358
+
359
+ this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
360
+
361
+ if ( this.options.probeType == 3 ) {
362
+ this.options.useTransition = false; }
363
+
364
+ // INSERT POINT: NORMALIZATION
365
+
366
+ // Some defaults
367
+ this.x = 0;
368
+ this.y = 0;
369
+ this.directionX = 0;
370
+ this.directionY = 0;
371
+ this._events = {};
372
+
373
+ // INSERT POINT: DEFAULTS
374
+
375
+ this._init();
376
+ this.refresh();
377
+
378
+ this.scrollTo(this.options.startX, this.options.startY);
379
+ this.enable();
380
+ }
381
+
382
+ IScroll.prototype = {
383
+ version: '5.2.0',
384
+
385
+ _init: function () {
386
+ this._initEvents();
387
+
388
+ if ( this.options.scrollbars || this.options.indicators ) {
389
+ this._initIndicators();
390
+ }
391
+
392
+ if ( this.options.mouseWheel ) {
393
+ this._initWheel();
394
+ }
395
+
396
+ if ( this.options.snap ) {
397
+ this._initSnap();
398
+ }
399
+
400
+ if ( this.options.keyBindings ) {
401
+ this._initKeys();
402
+ }
403
+
404
+ // INSERT POINT: _init
405
+
406
+ },
407
+
408
+ destroy: function () {
409
+ this._initEvents(true);
410
+ clearTimeout(this.resizeTimeout);
411
+ this.resizeTimeout = null;
412
+ this._execEvent('destroy');
413
+ },
414
+
415
+ _transitionEnd: function (e) {
416
+ if ( e.target != this.scroller || !this.isInTransition ) {
417
+ return;
418
+ }
419
+
420
+ this._transitionTime();
421
+ if ( !this.resetPosition(this.options.bounceTime) ) {
422
+ this.isInTransition = false;
423
+ this._execEvent('scrollEnd');
424
+ }
425
+ },
426
+
427
+ _start: function (e) {
428
+ // React to left mouse button only
429
+ if ( utils.eventType[e.type] != 1 ) {
430
+ // for button property
431
+ // http://unixpapa.com/js/mouse.html
432
+ var button;
433
+ if (!e.which) {
434
+ /* IE case */
435
+ button = (e.button < 2) ? 0 :
436
+ ((e.button == 4) ? 1 : 2);
437
+ } else {
438
+ /* All others */
439
+ button = e.button;
440
+ }
441
+ if ( button !== 0 ) {
442
+ return;
443
+ }
444
+ }
445
+
446
+ if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
447
+ return;
448
+ }
449
+
450
+ if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
451
+ e.preventDefault();
452
+ }
453
+
454
+ var point = e.touches ? e.touches[0] : e,
455
+ pos;
456
+
457
+ this.initiated = utils.eventType[e.type];
458
+ this.moved = false;
459
+ this.distX = 0;
460
+ this.distY = 0;
461
+ this.directionX = 0;
462
+ this.directionY = 0;
463
+ this.directionLocked = 0;
464
+
465
+ this.startTime = utils.getTime();
466
+
467
+ if ( this.options.useTransition && this.isInTransition ) {
468
+ this._transitionTime();
469
+ this.isInTransition = false;
470
+ pos = this.getComputedPosition();
471
+ this._translate(Math.round(pos.x), Math.round(pos.y));
472
+ this._execEvent('scrollEnd');
473
+ } else if ( !this.options.useTransition && this.isAnimating ) {
474
+ this.isAnimating = false;
475
+ this._execEvent('scrollEnd');
476
+ }
477
+
478
+ this.startX = this.x;
479
+ this.startY = this.y;
480
+ this.absStartX = this.x;
481
+ this.absStartY = this.y;
482
+ this.pointX = point.pageX;
483
+ this.pointY = point.pageY;
484
+
485
+ this._execEvent('beforeScrollStart');
486
+ },
487
+
488
+ _move: function (e) {
489
+ if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
490
+ return;
491
+ }
492
+
493
+ if ( this.options.preventDefault ) { // increases performance on Android? TODO: check!
494
+ e.preventDefault();
495
+ }
496
+
497
+ var point = e.touches ? e.touches[0] : e,
498
+ deltaX = point.pageX - this.pointX,
499
+ deltaY = point.pageY - this.pointY,
500
+ timestamp = utils.getTime(),
501
+ newX, newY,
502
+ absDistX, absDistY;
503
+
504
+ this.pointX = point.pageX;
505
+ this.pointY = point.pageY;
506
+
507
+ this.distX += deltaX;
508
+ this.distY += deltaY;
509
+ absDistX = Math.abs(this.distX);
510
+ absDistY = Math.abs(this.distY);
511
+
512
+ // We need to move at least 10 pixels for the scrolling to initiate
513
+ if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
514
+ return;
515
+ }
516
+
517
+ // If you are scrolling in one direction lock the other
518
+ if ( !this.directionLocked && !this.options.freeScroll ) {
519
+ if ( absDistX > absDistY + this.options.directionLockThreshold ) {
520
+ this.directionLocked = 'h'; // lock horizontally
521
+ } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
522
+ this.directionLocked = 'v'; // lock vertically
523
+ } else {
524
+ this.directionLocked = 'n'; // no lock
525
+ }
526
+ }
527
+
528
+ if ( this.directionLocked == 'h' ) {
529
+ if ( this.options.eventPassthrough == 'vertical' ) {
530
+ e.preventDefault();
531
+ } else if ( this.options.eventPassthrough == 'horizontal' ) {
532
+ this.initiated = false;
533
+ return;
534
+ }
535
+
536
+ deltaY = 0;
537
+ } else if ( this.directionLocked == 'v' ) {
538
+ if ( this.options.eventPassthrough == 'horizontal' ) {
539
+ e.preventDefault();
540
+ } else if ( this.options.eventPassthrough == 'vertical' ) {
541
+ this.initiated = false;
542
+ return;
543
+ }
544
+
545
+ deltaX = 0;
546
+ }
547
+
548
+ deltaX = this.hasHorizontalScroll ? deltaX : 0;
549
+ deltaY = this.hasVerticalScroll ? deltaY : 0;
550
+
551
+ newX = this.x + deltaX;
552
+ newY = this.y + deltaY;
553
+
554
+ // Slow down if outside of the boundaries
555
+ if ( newX > 0 || newX < this.maxScrollX ) {
556
+ newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
557
+ }
558
+ if ( newY > 0 || newY < this.maxScrollY ) {
559
+ newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
560
+ }
561
+
562
+ this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
563
+ this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
564
+
565
+ if ( !this.moved ) {
566
+ this._execEvent('scrollStart');
567
+ }
568
+
569
+ this.moved = true;
570
+
571
+ this._translate(newX, newY);
572
+
573
+ /* REPLACE START: _move */
574
+ if ( timestamp - this.startTime > 300 ) {
575
+ this.startTime = timestamp;
576
+ this.startX = this.x;
577
+ this.startY = this.y;
578
+
579
+ if ( this.options.probeType == 1 ) {
580
+ this._execEvent('scroll');
581
+ }
582
+ }
583
+
584
+ if ( this.options.probeType > 1 ) {
585
+ this._execEvent('scroll');
586
+ }
587
+ /* REPLACE END: _move */
588
+
589
+ if (this.options.stopPropagation) {
590
+ e.stopPropagation();
591
+ }
592
+
593
+ },
594
+
595
+ _end: function (e) {
596
+ if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
597
+ return;
598
+ }
599
+
600
+ if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
601
+ e.preventDefault();
602
+ }
603
+
604
+ var point = e.changedTouches ? e.changedTouches[0] : e,
605
+ momentumX,
606
+ momentumY,
607
+ duration = utils.getTime() - this.startTime,
608
+ newX = Math.round(this.x),
609
+ newY = Math.round(this.y),
610
+ distanceX = Math.abs(newX - this.startX),
611
+ distanceY = Math.abs(newY - this.startY),
612
+ time = 0,
613
+ easing = '';
614
+
615
+ this.isInTransition = 0;
616
+ this.initiated = 0;
617
+ this.endTime = utils.getTime();
618
+
619
+ // reset if we are outside of the boundaries
620
+ if ( this.resetPosition(this.options.bounceTime) ) {
621
+ return;
622
+ }
623
+
624
+ this.scrollTo(newX, newY); // ensures that the last position is rounded
625
+
626
+ // we scrolled less than 10 pixels
627
+ if ( !this.moved ) {
628
+ if ( this.options.tap ) {
629
+ utils.tap(e, this.options.tap);
630
+ }
631
+
632
+ if ( this.options.click ) {
633
+ utils.click(e);
634
+ }
635
+
636
+ this._execEvent('scrollCancel');
637
+ return;
638
+ }
639
+
640
+ if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
641
+ this._execEvent('flick');
642
+ return;
643
+ }
644
+
645
+ // start momentum animation if needed
646
+ if ( this.options.momentum && duration < 300 ) {
647
+ momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };
648
+ momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };
649
+ newX = momentumX.destination;
650
+ newY = momentumY.destination;
651
+ time = Math.max(momentumX.duration, momentumY.duration);
652
+ this.isInTransition = 1;
653
+ }
654
+
655
+
656
+ if ( this.options.snap ) {
657
+ var snap = this._nearestSnap(newX, newY);
658
+ this.currentPage = snap;
659
+ time = this.options.snapSpeed || Math.max(
660
+ Math.max(
661
+ Math.min(Math.abs(newX - snap.x), 1000),
662
+ Math.min(Math.abs(newY - snap.y), 1000)
663
+ ), 300);
664
+ newX = snap.x;
665
+ newY = snap.y;
666
+
667
+ this.directionX = 0;
668
+ this.directionY = 0;
669
+ easing = this.options.bounceEasing;
670
+ }
671
+
672
+ // INSERT POINT: _end
673
+
674
+ if ( newX != this.x || newY != this.y ) {
675
+ // change easing function when scroller goes out of the boundaries
676
+ if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
677
+ easing = utils.ease.quadratic;
678
+ }
679
+
680
+ this.scrollTo(newX, newY, time, easing);
681
+ return;
682
+ }
683
+
684
+ this._execEvent('scrollEnd');
685
+ },
686
+
687
+ _resize: function () {
688
+ var that = this;
689
+
690
+ clearTimeout(this.resizeTimeout);
691
+
692
+ this.resizeTimeout = setTimeout(function () {
693
+ that.refresh();
694
+ }, this.options.resizePolling);
695
+ },
696
+
697
+ resetPosition: function (time) {
698
+ var x = this.x,
699
+ y = this.y;
700
+
701
+ time = time || 0;
702
+
703
+ if ( !this.hasHorizontalScroll || this.x > 0 ) {
704
+ x = 0;
705
+ } else if ( this.x < this.maxScrollX ) {
706
+ x = this.maxScrollX;
707
+ }
708
+
709
+ if ( !this.hasVerticalScroll || this.y > 0 ) {
710
+ y = 0;
711
+ } else if ( this.y < this.maxScrollY ) {
712
+ y = this.maxScrollY;
713
+ }
714
+
715
+ if ( x == this.x && y == this.y ) {
716
+ return false;
717
+ }
718
+
719
+ this.scrollTo(x, y, time, this.options.bounceEasing);
720
+
721
+ return true;
722
+ },
723
+
724
+ disable: function () {
725
+ this.enabled = false;
726
+ },
727
+
728
+ enable: function () {
729
+ this.enabled = true;
730
+ },
731
+
732
+ refresh: function () {
733
+ var rf = this.wrapper.offsetHeight; // Force reflow
734
+
735
+ this.wrapperWidth = this.wrapper.clientWidth;
736
+ this.wrapperHeight = this.wrapper.clientHeight;
737
+
738
+ /* REPLACE START: refresh */
739
+
740
+ this.scrollerWidth = this.scroller.offsetWidth;
741
+ this.scrollerHeight = this.scroller.offsetHeight;
742
+
743
+ this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
744
+ this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
745
+
746
+ /* REPLACE END: refresh */
747
+
748
+ this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
749
+ this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
750
+
751
+ if ( !this.hasHorizontalScroll ) {
752
+ this.maxScrollX = 0;
753
+ this.scrollerWidth = this.wrapperWidth;
754
+ }
755
+
756
+ if ( !this.hasVerticalScroll ) {
757
+ this.maxScrollY = 0;
758
+ this.scrollerHeight = this.wrapperHeight;
759
+ }
760
+
761
+ this.endTime = 0;
762
+ this.directionX = 0;
763
+ this.directionY = 0;
764
+
765
+ this.wrapperOffset = utils.offset(this.wrapper);
766
+
767
+ this._execEvent('refresh');
768
+
769
+ this.resetPosition();
770
+
771
+ // INSERT POINT: _refresh
772
+
773
+ },
774
+
775
+ on: function (type, fn) {
776
+ if ( !this._events[type] ) {
777
+ this._events[type] = [];
778
+ }
779
+
780
+ this._events[type].push(fn);
781
+ },
782
+
783
+ off: function (type, fn) {
784
+ if ( !this._events[type] ) {
785
+ return;
786
+ }
787
+
788
+ var index = this._events[type].indexOf(fn);
789
+
790
+ if ( index > -1 ) {
791
+ this._events[type].splice(index, 1);
792
+ }
793
+ },
794
+
795
+ _execEvent: function (type) {
796
+ if ( !this._events[type] ) {
797
+ return;
798
+ }
799
+
800
+ var i = 0,
801
+ l = this._events[type].length;
802
+
803
+ if ( !l ) {
804
+ return;
805
+ }
806
+
807
+ for ( ; i < l; i++ ) {
808
+ this._events[type][i].apply(this, [].slice.call(arguments, 1));
809
+ }
810
+ },
811
+
812
+ scrollBy: function (x, y, time, easing) {
813
+ x = this.x + x;
814
+ y = this.y + y;
815
+ time = time || 0;
816
+
817
+ this.scrollTo(x, y, time, easing);
818
+ },
819
+
820
+ scrollTo: function (x, y, time, easing) {
821
+ easing = easing || utils.ease.circular;
822
+
823
+ this.isInTransition = this.options.useTransition && time > 0;
824
+ var transitionType = this.options.useTransition && easing.style;
825
+ if ( !time || transitionType ) {
826
+ if(transitionType) {
827
+ this._transitionTimingFunction(easing.style);
828
+ this._transitionTime(time);
829
+ }
830
+ this._translate(x, y);
831
+ } else {
832
+ this._animate(x, y, time, easing.fn);
833
+ }
834
+ },
835
+
836
+ scrollToElement: function (el, time, offsetX, offsetY, easing) {
837
+ el = el.nodeType ? el : this.scroller.querySelector(el);
838
+
839
+ if ( !el ) {
840
+ return;
841
+ }
842
+
843
+ var pos = utils.offset(el);
844
+
845
+ pos.left -= this.wrapperOffset.left;
846
+ pos.top -= this.wrapperOffset.top;
847
+
848
+ // if offsetX/Y are true we center the element to the screen
849
+ if ( offsetX === true ) {
850
+ offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
851
+ }
852
+ if ( offsetY === true ) {
853
+ offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
854
+ }
855
+
856
+ pos.left -= offsetX || 0;
857
+ pos.top -= offsetY || 0;
858
+
859
+ pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
860
+ pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;
861
+
862
+ time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
863
+
864
+ this.scrollTo(pos.left, pos.top, time, easing);
865
+ },
866
+
867
+ _transitionTime: function (time) {
868
+ if (!this.options.useTransition) {
869
+ return;
870
+ }
871
+ time = time || 0;
872
+ var durationProp = utils.style.transitionDuration;
873
+ if(!durationProp) {
874
+ return;
875
+ }
876
+
877
+ this.scrollerStyle[durationProp] = time + 'ms';
878
+
879
+ if ( !time && utils.isBadAndroid ) {
880
+ this.scrollerStyle[durationProp] = '0.0001ms';
881
+ // remove 0.0001ms
882
+ var self = this;
883
+ rAF(function() {
884
+ if(self.scrollerStyle[durationProp] === '0.0001ms') {
885
+ self.scrollerStyle[durationProp] = '0s';
886
+ }
887
+ });
888
+ }
889
+
890
+
891
+ if ( this.indicators ) {
892
+ for ( var i = this.indicators.length; i--; ) {
893
+ this.indicators[i].transitionTime(time);
894
+ }
895
+ }
896
+
897
+
898
+ // INSERT POINT: _transitionTime
899
+
900
+ },
901
+
902
+ _transitionTimingFunction: function (easing) {
903
+ this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
904
+
905
+
906
+ if ( this.indicators ) {
907
+ for ( var i = this.indicators.length; i--; ) {
908
+ this.indicators[i].transitionTimingFunction(easing);
909
+ }
910
+ }
911
+
912
+
913
+ // INSERT POINT: _transitionTimingFunction
914
+
915
+ },
916
+
917
+ _translate: function (x, y) {
918
+ if ( this.options.useTransform ) {
919
+
920
+ /* REPLACE START: _translate */
921
+
922
+ this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
923
+
924
+ /* REPLACE END: _translate */
925
+
926
+ } else {
927
+ x = Math.round(x);
928
+ y = Math.round(y);
929
+ this.scrollerStyle.left = x + 'px';
930
+ this.scrollerStyle.top = y + 'px';
931
+ }
932
+
933
+ this.x = x;
934
+ this.y = y;
935
+
936
+
937
+ if ( this.indicators ) {
938
+ for ( var i = this.indicators.length; i--; ) {
939
+ this.indicators[i].updatePosition();
940
+ }
941
+ }
942
+
943
+
944
+ // INSERT POINT: _translate
945
+
946
+ },
947
+
948
+ _initEvents: function (remove) {
949
+ var eventType = remove ? utils.removeEvent : utils.addEvent,
950
+ target = this.options.bindToWrapper ? this.wrapper : window;
951
+
952
+ eventType(window, 'orientationchange', this);
953
+ eventType(window, 'resize', this);
954
+
955
+ if ( this.options.click ) {
956
+ eventType(this.wrapper, 'click', this, true);
957
+ }
958
+
959
+ if ( !this.options.disableMouse ) {
960
+ eventType(this.wrapper, 'mousedown', this);
961
+ eventType(target, 'mousemove', this);
962
+ eventType(target, 'mousecancel', this);
963
+ eventType(target, 'mouseup', this);
964
+ }
965
+
966
+ if ( utils.hasPointer && !this.options.disablePointer ) {
967
+ eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
968
+ eventType(target, utils.prefixPointerEvent('pointermove'), this);
969
+ eventType(target, utils.prefixPointerEvent('pointercancel'), this);
970
+ eventType(target, utils.prefixPointerEvent('pointerup'), this);
971
+ }
972
+
973
+ if ( utils.hasTouch && !this.options.disableTouch ) {
974
+ eventType(this.wrapper, 'touchstart', this);
975
+ eventType(target, 'touchmove', this);
976
+ eventType(target, 'touchcancel', this);
977
+ eventType(target, 'touchend', this);
978
+ }
979
+
980
+ eventType(this.scroller, 'transitionend', this);
981
+ eventType(this.scroller, 'webkitTransitionEnd', this);
982
+ eventType(this.scroller, 'oTransitionEnd', this);
983
+ eventType(this.scroller, 'MSTransitionEnd', this);
984
+ },
985
+
986
+ getComputedPosition: function () {
987
+ var matrix = window.getComputedStyle(this.scroller, null),
988
+ x, y;
989
+
990
+ if ( this.options.useTransform ) {
991
+ matrix = matrix[utils.style.transform].split(')')[0].split(', ');
992
+ x = +(matrix[12] || matrix[4]);
993
+ y = +(matrix[13] || matrix[5]);
994
+ } else {
995
+ x = +matrix.left.replace(/[^-\d.]/g, '');
996
+ y = +matrix.top.replace(/[^-\d.]/g, '');
997
+ }
998
+
999
+ return { x: x, y: y };
1000
+ },
1001
+ _initIndicators: function () {
1002
+ var interactive = this.options.interactiveScrollbars,
1003
+ customStyle = typeof this.options.scrollbars != 'string',
1004
+ indicators = [],
1005
+ indicator;
1006
+
1007
+ var that = this;
1008
+
1009
+ this.indicators = [];
1010
+
1011
+ if ( this.options.scrollbars ) {
1012
+ // Vertical scrollbar
1013
+ if ( this.options.scrollY ) {
1014
+ indicator = {
1015
+ el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
1016
+ interactive: interactive,
1017
+ defaultScrollbars: true,
1018
+ customStyle: customStyle,
1019
+ resize: this.options.resizeScrollbars,
1020
+ shrink: this.options.shrinkScrollbars,
1021
+ fade: this.options.fadeScrollbars,
1022
+ listenX: false
1023
+ };
1024
+
1025
+ this.wrapper.appendChild(indicator.el);
1026
+ indicators.push(indicator);
1027
+ }
1028
+
1029
+ // Horizontal scrollbar
1030
+ if ( this.options.scrollX ) {
1031
+ indicator = {
1032
+ el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
1033
+ interactive: interactive,
1034
+ defaultScrollbars: true,
1035
+ customStyle: customStyle,
1036
+ resize: this.options.resizeScrollbars,
1037
+ shrink: this.options.shrinkScrollbars,
1038
+ fade: this.options.fadeScrollbars,
1039
+ listenY: false
1040
+ };
1041
+
1042
+ this.wrapper.appendChild(indicator.el);
1043
+ indicators.push(indicator);
1044
+ }
1045
+ }
1046
+
1047
+ if ( this.options.indicators ) {
1048
+ // TODO: check concat compatibility
1049
+ indicators = indicators.concat(this.options.indicators);
1050
+ }
1051
+
1052
+ for ( var i = indicators.length; i--; ) {
1053
+ this.indicators.push( new Indicator(this, indicators[i]) );
1054
+ }
1055
+
1056
+ // TODO: check if we can use array.map (wide compatibility and performance issues)
1057
+ function _indicatorsMap (fn) {
1058
+ if (that.indicators) {
1059
+ for ( var i = that.indicators.length; i--; ) {
1060
+ fn.call(that.indicators[i]);
1061
+ }
1062
+ }
1063
+ }
1064
+
1065
+ if ( this.options.fadeScrollbars ) {
1066
+ this.on('scrollEnd', function () {
1067
+ _indicatorsMap(function () {
1068
+ this.fade();
1069
+ });
1070
+ });
1071
+
1072
+ this.on('scrollCancel', function () {
1073
+ _indicatorsMap(function () {
1074
+ this.fade();
1075
+ });
1076
+ });
1077
+
1078
+ this.on('scrollStart', function () {
1079
+ _indicatorsMap(function () {
1080
+ this.fade(1);
1081
+ });
1082
+ });
1083
+
1084
+ this.on('beforeScrollStart', function () {
1085
+ _indicatorsMap(function () {
1086
+ this.fade(1, true);
1087
+ });
1088
+ });
1089
+ }
1090
+
1091
+
1092
+ this.on('refresh', function () {
1093
+ _indicatorsMap(function () {
1094
+ this.refresh();
1095
+ });
1096
+ });
1097
+
1098
+ this.on('destroy', function () {
1099
+ _indicatorsMap(function () {
1100
+ this.destroy();
1101
+ });
1102
+
1103
+ delete this.indicators;
1104
+ });
1105
+ },
1106
+
1107
+ _initWheel: function () {
1108
+ utils.addEvent(this.wrapper, 'wheel', this);
1109
+ utils.addEvent(this.wrapper, 'mousewheel', this);
1110
+ utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
1111
+
1112
+ this.on('destroy', function () {
1113
+ clearTimeout(this.wheelTimeout);
1114
+ this.wheelTimeout = null;
1115
+ utils.removeEvent(this.wrapper, 'wheel', this);
1116
+ utils.removeEvent(this.wrapper, 'mousewheel', this);
1117
+ utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
1118
+ });
1119
+ },
1120
+
1121
+ _wheel: function (e) {
1122
+ if ( !this.enabled ) {
1123
+ return;
1124
+ }
1125
+
1126
+ e.preventDefault();
1127
+
1128
+ var wheelDeltaX, wheelDeltaY,
1129
+ newX, newY,
1130
+ that = this;
1131
+
1132
+ if ( this.wheelTimeout === undefined ) {
1133
+ that._execEvent('scrollStart');
1134
+ }
1135
+
1136
+ // Execute the scrollEnd event after 400ms the wheel stopped scrolling
1137
+ clearTimeout(this.wheelTimeout);
1138
+ this.wheelTimeout = setTimeout(function () {
1139
+ if(!that.options.snap) {
1140
+ that._execEvent('scrollEnd');
1141
+ }
1142
+ that.wheelTimeout = undefined;
1143
+ }, 400);
1144
+
1145
+ if ( 'deltaX' in e ) {
1146
+ if (e.deltaMode === 1) {
1147
+ wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
1148
+ wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
1149
+ } else {
1150
+ wheelDeltaX = -e.deltaX;
1151
+ wheelDeltaY = -e.deltaY;
1152
+ }
1153
+ } else if ( 'wheelDeltaX' in e ) {
1154
+ wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
1155
+ wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
1156
+ } else if ( 'wheelDelta' in e ) {
1157
+ wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
1158
+ } else if ( 'detail' in e ) {
1159
+ wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
1160
+ } else {
1161
+ return;
1162
+ }
1163
+
1164
+ wheelDeltaX *= this.options.invertWheelDirection;
1165
+ wheelDeltaY *= this.options.invertWheelDirection;
1166
+
1167
+ if ( !this.hasVerticalScroll ) {
1168
+ wheelDeltaX = wheelDeltaY;
1169
+ wheelDeltaY = 0;
1170
+ }
1171
+
1172
+ if ( this.options.snap ) {
1173
+ newX = this.currentPage.pageX;
1174
+ newY = this.currentPage.pageY;
1175
+
1176
+ if ( wheelDeltaX > 0 ) {
1177
+ newX--;
1178
+ } else if ( wheelDeltaX < 0 ) {
1179
+ newX++;
1180
+ }
1181
+
1182
+ if ( wheelDeltaY > 0 ) {
1183
+ newY--;
1184
+ } else if ( wheelDeltaY < 0 ) {
1185
+ newY++;
1186
+ }
1187
+
1188
+ this.goToPage(newX, newY);
1189
+
1190
+ return;
1191
+ }
1192
+
1193
+ newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
1194
+ newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
1195
+
1196
+ this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
1197
+ this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
1198
+
1199
+ if ( newX > 0 ) {
1200
+ newX = 0;
1201
+ } else if ( newX < this.maxScrollX ) {
1202
+ newX = this.maxScrollX;
1203
+ }
1204
+
1205
+ if ( newY > 0 ) {
1206
+ newY = 0;
1207
+ } else if ( newY < this.maxScrollY ) {
1208
+ newY = this.maxScrollY;
1209
+ }
1210
+
1211
+ this.scrollTo(newX, newY, 0);
1212
+
1213
+ if ( this.options.probeType > 1 ) {
1214
+ this._execEvent('scroll');
1215
+ }
1216
+
1217
+ // INSERT POINT: _wheel
1218
+ },
1219
+
1220
+ _initSnap: function () {
1221
+ this.currentPage = {};
1222
+
1223
+ if ( typeof this.options.snap == 'string' ) {
1224
+ this.options.snap = this.scroller.querySelectorAll(this.options.snap);
1225
+ }
1226
+
1227
+ this.on('refresh', function () {
1228
+ var i = 0, l,
1229
+ m = 0, n,
1230
+ cx, cy,
1231
+ x = 0, y,
1232
+ stepX = this.options.snapStepX || this.wrapperWidth,
1233
+ stepY = this.options.snapStepY || this.wrapperHeight,
1234
+ el;
1235
+
1236
+ this.pages = [];
1237
+
1238
+ if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
1239
+ return;
1240
+ }
1241
+
1242
+ if ( this.options.snap === true ) {
1243
+ cx = Math.round( stepX / 2 );
1244
+ cy = Math.round( stepY / 2 );
1245
+
1246
+ while ( x > -this.scrollerWidth ) {
1247
+ this.pages[i] = [];
1248
+ l = 0;
1249
+ y = 0;
1250
+
1251
+ while ( y > -this.scrollerHeight ) {
1252
+ this.pages[i][l] = {
1253
+ x: Math.max(x, this.maxScrollX),
1254
+ y: Math.max(y, this.maxScrollY),
1255
+ width: stepX,
1256
+ height: stepY,
1257
+ cx: x - cx,
1258
+ cy: y - cy
1259
+ };
1260
+
1261
+ y -= stepY;
1262
+ l++;
1263
+ }
1264
+
1265
+ x -= stepX;
1266
+ i++;
1267
+ }
1268
+ } else {
1269
+ el = this.options.snap;
1270
+ l = el.length;
1271
+ n = -1;
1272
+
1273
+ for ( ; i < l; i++ ) {
1274
+ if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
1275
+ m = 0;
1276
+ n++;
1277
+ }
1278
+
1279
+ if ( !this.pages[m] ) {
1280
+ this.pages[m] = [];
1281
+ }
1282
+
1283
+ x = Math.max(-el[i].offsetLeft, this.maxScrollX);
1284
+ y = Math.max(-el[i].offsetTop, this.maxScrollY);
1285
+ cx = x - Math.round(el[i].offsetWidth / 2);
1286
+ cy = y - Math.round(el[i].offsetHeight / 2);
1287
+
1288
+ this.pages[m][n] = {
1289
+ x: x,
1290
+ y: y,
1291
+ width: el[i].offsetWidth,
1292
+ height: el[i].offsetHeight,
1293
+ cx: cx,
1294
+ cy: cy
1295
+ };
1296
+
1297
+ if ( x > this.maxScrollX ) {
1298
+ m++;
1299
+ }
1300
+ }
1301
+ }
1302
+
1303
+ this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
1304
+
1305
+ // Update snap threshold if needed
1306
+ if ( this.options.snapThreshold % 1 === 0 ) {
1307
+ this.snapThresholdX = this.options.snapThreshold;
1308
+ this.snapThresholdY = this.options.snapThreshold;
1309
+ } else {
1310
+ this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
1311
+ this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
1312
+ }
1313
+ });
1314
+
1315
+ this.on('flick', function () {
1316
+ var time = this.options.snapSpeed || Math.max(
1317
+ Math.max(
1318
+ Math.min(Math.abs(this.x - this.startX), 1000),
1319
+ Math.min(Math.abs(this.y - this.startY), 1000)
1320
+ ), 300);
1321
+
1322
+ this.goToPage(
1323
+ this.currentPage.pageX + this.directionX,
1324
+ this.currentPage.pageY + this.directionY,
1325
+ time
1326
+ );
1327
+ });
1328
+ },
1329
+
1330
+ _nearestSnap: function (x, y) {
1331
+ if ( !this.pages.length ) {
1332
+ return { x: 0, y: 0, pageX: 0, pageY: 0 };
1333
+ }
1334
+
1335
+ var i = 0,
1336
+ l = this.pages.length,
1337
+ m = 0;
1338
+
1339
+ // Check if we exceeded the snap threshold
1340
+ if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
1341
+ Math.abs(y - this.absStartY) < this.snapThresholdY ) {
1342
+ return this.currentPage;
1343
+ }
1344
+
1345
+ if ( x > 0 ) {
1346
+ x = 0;
1347
+ } else if ( x < this.maxScrollX ) {
1348
+ x = this.maxScrollX;
1349
+ }
1350
+
1351
+ if ( y > 0 ) {
1352
+ y = 0;
1353
+ } else if ( y < this.maxScrollY ) {
1354
+ y = this.maxScrollY;
1355
+ }
1356
+
1357
+ for ( ; i < l; i++ ) {
1358
+ if ( x >= this.pages[i][0].cx ) {
1359
+ x = this.pages[i][0].x;
1360
+ break;
1361
+ }
1362
+ }
1363
+
1364
+ l = this.pages[i].length;
1365
+
1366
+ for ( ; m < l; m++ ) {
1367
+ if ( y >= this.pages[0][m].cy ) {
1368
+ y = this.pages[0][m].y;
1369
+ break;
1370
+ }
1371
+ }
1372
+
1373
+ if ( i == this.currentPage.pageX ) {
1374
+ i += this.directionX;
1375
+
1376
+ if ( i < 0 ) {
1377
+ i = 0;
1378
+ } else if ( i >= this.pages.length ) {
1379
+ i = this.pages.length - 1;
1380
+ }
1381
+
1382
+ x = this.pages[i][0].x;
1383
+ }
1384
+
1385
+ if ( m == this.currentPage.pageY ) {
1386
+ m += this.directionY;
1387
+
1388
+ if ( m < 0 ) {
1389
+ m = 0;
1390
+ } else if ( m >= this.pages[0].length ) {
1391
+ m = this.pages[0].length - 1;
1392
+ }
1393
+
1394
+ y = this.pages[0][m].y;
1395
+ }
1396
+
1397
+ return {
1398
+ x: x,
1399
+ y: y,
1400
+ pageX: i,
1401
+ pageY: m
1402
+ };
1403
+ },
1404
+
1405
+ goToPage: function (x, y, time, easing) {
1406
+ easing = easing || this.options.bounceEasing;
1407
+
1408
+ if ( x >= this.pages.length ) {
1409
+ x = this.pages.length - 1;
1410
+ } else if ( x < 0 ) {
1411
+ x = 0;
1412
+ }
1413
+
1414
+ if ( y >= this.pages[x].length ) {
1415
+ y = this.pages[x].length - 1;
1416
+ } else if ( y < 0 ) {
1417
+ y = 0;
1418
+ }
1419
+
1420
+ var posX = this.pages[x][y].x,
1421
+ posY = this.pages[x][y].y;
1422
+
1423
+ time = time === undefined ? this.options.snapSpeed || Math.max(
1424
+ Math.max(
1425
+ Math.min(Math.abs(posX - this.x), 1000),
1426
+ Math.min(Math.abs(posY - this.y), 1000)
1427
+ ), 300) : time;
1428
+
1429
+ this.currentPage = {
1430
+ x: posX,
1431
+ y: posY,
1432
+ pageX: x,
1433
+ pageY: y
1434
+ };
1435
+
1436
+ this.scrollTo(posX, posY, time, easing);
1437
+ },
1438
+
1439
+ next: function (time, easing) {
1440
+ var x = this.currentPage.pageX,
1441
+ y = this.currentPage.pageY;
1442
+
1443
+ x++;
1444
+
1445
+ if ( x >= this.pages.length && this.hasVerticalScroll ) {
1446
+ x = 0;
1447
+ y++;
1448
+ }
1449
+
1450
+ this.goToPage(x, y, time, easing);
1451
+ },
1452
+
1453
+ prev: function (time, easing) {
1454
+ var x = this.currentPage.pageX,
1455
+ y = this.currentPage.pageY;
1456
+
1457
+ x--;
1458
+
1459
+ if ( x < 0 && this.hasVerticalScroll ) {
1460
+ x = 0;
1461
+ y--;
1462
+ }
1463
+
1464
+ this.goToPage(x, y, time, easing);
1465
+ },
1466
+
1467
+ _initKeys: function (e) {
1468
+ // default key bindings
1469
+ var keys = {
1470
+ pageUp: 33,
1471
+ pageDown: 34,
1472
+ end: 35,
1473
+ home: 36,
1474
+ left: 37,
1475
+ up: 38,
1476
+ right: 39,
1477
+ down: 40
1478
+ };
1479
+ var i;
1480
+
1481
+ // if you give me characters I give you keycode
1482
+ if ( typeof this.options.keyBindings == 'object' ) {
1483
+ for ( i in this.options.keyBindings ) {
1484
+ if ( typeof this.options.keyBindings[i] == 'string' ) {
1485
+ this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);
1486
+ }
1487
+ }
1488
+ } else {
1489
+ this.options.keyBindings = {};
1490
+ }
1491
+
1492
+ for ( i in keys ) {
1493
+ this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
1494
+ }
1495
+
1496
+ utils.addEvent(window, 'keydown', this);
1497
+
1498
+ this.on('destroy', function () {
1499
+ utils.removeEvent(window, 'keydown', this);
1500
+ });
1501
+ },
1502
+
1503
+ _key: function (e) {
1504
+ if ( !this.enabled ) {
1505
+ return;
1506
+ }
1507
+
1508
+ var snap = this.options.snap, // we are using this alot, better to cache it
1509
+ newX = snap ? this.currentPage.pageX : this.x,
1510
+ newY = snap ? this.currentPage.pageY : this.y,
1511
+ now = utils.getTime(),
1512
+ prevTime = this.keyTime || 0,
1513
+ acceleration = 0.250,
1514
+ pos;
1515
+
1516
+ if ( this.options.useTransition && this.isInTransition ) {
1517
+ pos = this.getComputedPosition();
1518
+
1519
+ this._translate(Math.round(pos.x), Math.round(pos.y));
1520
+ this.isInTransition = false;
1521
+ }
1522
+
1523
+ this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
1524
+
1525
+ switch ( e.keyCode ) {
1526
+ case this.options.keyBindings.pageUp:
1527
+ if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
1528
+ newX += snap ? 1 : this.wrapperWidth;
1529
+ } else {
1530
+ newY += snap ? 1 : this.wrapperHeight;
1531
+ }
1532
+ break;
1533
+ case this.options.keyBindings.pageDown:
1534
+ if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
1535
+ newX -= snap ? 1 : this.wrapperWidth;
1536
+ } else {
1537
+ newY -= snap ? 1 : this.wrapperHeight;
1538
+ }
1539
+ break;
1540
+ case this.options.keyBindings.end:
1541
+ newX = snap ? this.pages.length-1 : this.maxScrollX;
1542
+ newY = snap ? this.pages[0].length-1 : this.maxScrollY;
1543
+ break;
1544
+ case this.options.keyBindings.home:
1545
+ newX = 0;
1546
+ newY = 0;
1547
+ break;
1548
+ case this.options.keyBindings.left:
1549
+ newX += snap ? -1 : 5 + this.keyAcceleration>>0;
1550
+ break;
1551
+ case this.options.keyBindings.up:
1552
+ newY += snap ? 1 : 5 + this.keyAcceleration>>0;
1553
+ break;
1554
+ case this.options.keyBindings.right:
1555
+ newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
1556
+ break;
1557
+ case this.options.keyBindings.down:
1558
+ newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
1559
+ break;
1560
+ default:
1561
+ return;
1562
+ }
1563
+
1564
+ if ( snap ) {
1565
+ this.goToPage(newX, newY);
1566
+ return;
1567
+ }
1568
+
1569
+ if ( newX > 0 ) {
1570
+ newX = 0;
1571
+ this.keyAcceleration = 0;
1572
+ } else if ( newX < this.maxScrollX ) {
1573
+ newX = this.maxScrollX;
1574
+ this.keyAcceleration = 0;
1575
+ }
1576
+
1577
+ if ( newY > 0 ) {
1578
+ newY = 0;
1579
+ this.keyAcceleration = 0;
1580
+ } else if ( newY < this.maxScrollY ) {
1581
+ newY = this.maxScrollY;
1582
+ this.keyAcceleration = 0;
1583
+ }
1584
+
1585
+ this.scrollTo(newX, newY, 0);
1586
+
1587
+ this.keyTime = now;
1588
+ },
1589
+
1590
+ _animate: function (destX, destY, duration, easingFn) {
1591
+ var that = this,
1592
+ startX = this.x,
1593
+ startY = this.y,
1594
+ startTime = utils.getTime(),
1595
+ destTime = startTime + duration;
1596
+
1597
+ function step () {
1598
+ var now = utils.getTime(),
1599
+ newX, newY,
1600
+ easing;
1601
+
1602
+ if ( now >= destTime ) {
1603
+ that.isAnimating = false;
1604
+ that._translate(destX, destY);
1605
+
1606
+ if ( !that.resetPosition(that.options.bounceTime) ) {
1607
+ that._execEvent('scrollEnd');
1608
+ }
1609
+
1610
+ return;
1611
+ }
1612
+
1613
+ now = ( now - startTime ) / duration;
1614
+ easing = easingFn(now);
1615
+ newX = ( destX - startX ) * easing + startX;
1616
+ newY = ( destY - startY ) * easing + startY;
1617
+ that._translate(newX, newY);
1618
+
1619
+ if ( that.isAnimating ) {
1620
+ rAF(step);
1621
+ }
1622
+
1623
+ if ( that.options.probeType == 3 ) {
1624
+ that._execEvent('scroll');
1625
+ }
1626
+ }
1627
+
1628
+ this.isAnimating = true;
1629
+ step();
1630
+ },
1631
+
1632
+ handleEvent: function (e) {
1633
+ switch ( e.type ) {
1634
+ case 'touchstart':
1635
+ case 'pointerdown':
1636
+ case 'MSPointerDown':
1637
+ case 'mousedown':
1638
+ this._start(e);
1639
+ break;
1640
+ case 'touchmove':
1641
+ case 'pointermove':
1642
+ case 'MSPointerMove':
1643
+ case 'mousemove':
1644
+ this._move(e);
1645
+ break;
1646
+ case 'touchend':
1647
+ case 'pointerup':
1648
+ case 'MSPointerUp':
1649
+ case 'mouseup':
1650
+ case 'touchcancel':
1651
+ case 'pointercancel':
1652
+ case 'MSPointerCancel':
1653
+ case 'mousecancel':
1654
+ this._end(e);
1655
+ break;
1656
+ case 'orientationchange':
1657
+ case 'resize':
1658
+ this._resize();
1659
+ break;
1660
+ case 'transitionend':
1661
+ case 'webkitTransitionEnd':
1662
+ case 'oTransitionEnd':
1663
+ case 'MSTransitionEnd':
1664
+ this._transitionEnd(e);
1665
+ break;
1666
+ case 'wheel':
1667
+ case 'DOMMouseScroll':
1668
+ case 'mousewheel':
1669
+ this._wheel(e);
1670
+ break;
1671
+ case 'keydown':
1672
+ this._key(e);
1673
+ break;
1674
+ case 'click':
1675
+ if ( this.enabled && !e._constructed ) {
1676
+ e.preventDefault();
1677
+ e.stopPropagation();
1678
+ }
1679
+ break;
1680
+ }
1681
+ }
1682
+ };
1683
+ function createDefaultScrollbar (direction, interactive, type) {
1684
+ var scrollbar = document.createElement('div'),
1685
+ indicator = document.createElement('div');
1686
+
1687
+ if ( type === true ) {
1688
+ scrollbar.style.cssText = 'position:absolute;z-index:9999';
1689
+ 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';
1690
+ }
1691
+
1692
+ indicator.className = 'iScrollIndicator';
1693
+
1694
+ if ( direction == 'h' ) {
1695
+ if ( type === true ) {
1696
+ scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
1697
+ indicator.style.height = '100%';
1698
+ }
1699
+ scrollbar.className = 'iScrollHorizontalScrollbar';
1700
+ } else {
1701
+ if ( type === true ) {
1702
+ scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
1703
+ indicator.style.width = '100%';
1704
+ }
1705
+ scrollbar.className = 'iScrollVerticalScrollbar';
1706
+ }
1707
+
1708
+ scrollbar.style.cssText += ';overflow:hidden';
1709
+
1710
+ if ( !interactive ) {
1711
+ scrollbar.style.pointerEvents = 'none';
1712
+ }
1713
+
1714
+ scrollbar.appendChild(indicator);
1715
+
1716
+ return scrollbar;
1717
+ }
1718
+
1719
+ function Indicator (scroller, options) {
1720
+ this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
1721
+ this.wrapperStyle = this.wrapper.style;
1722
+ this.indicator = this.wrapper.children[0];
1723
+ this.indicatorStyle = this.indicator.style;
1724
+ this.scroller = scroller;
1725
+
1726
+ this.options = {
1727
+ listenX: true,
1728
+ listenY: true,
1729
+ interactive: false,
1730
+ resize: true,
1731
+ defaultScrollbars: false,
1732
+ shrink: false,
1733
+ fade: false,
1734
+ speedRatioX: 0,
1735
+ speedRatioY: 0
1736
+ };
1737
+
1738
+ for ( var i in options ) {
1739
+ this.options[i] = options[i];
1740
+ }
1741
+
1742
+ this.sizeRatioX = 1;
1743
+ this.sizeRatioY = 1;
1744
+ this.maxPosX = 0;
1745
+ this.maxPosY = 0;
1746
+
1747
+ if ( this.options.interactive ) {
1748
+ if ( !this.options.disableTouch ) {
1749
+ utils.addEvent(this.indicator, 'touchstart', this);
1750
+ utils.addEvent(window, 'touchend', this);
1751
+ }
1752
+ if ( !this.options.disablePointer ) {
1753
+ utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
1754
+ utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
1755
+ }
1756
+ if ( !this.options.disableMouse ) {
1757
+ utils.addEvent(this.indicator, 'mousedown', this);
1758
+ utils.addEvent(window, 'mouseup', this);
1759
+ }
1760
+ }
1761
+
1762
+ if ( this.options.fade ) {
1763
+ this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
1764
+ var durationProp = utils.style.transitionDuration;
1765
+ if(!durationProp) {
1766
+ return;
1767
+ }
1768
+ this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
1769
+ // remove 0.0001ms
1770
+ var self = this;
1771
+ if(utils.isBadAndroid) {
1772
+ rAF(function() {
1773
+ if(self.wrapperStyle[durationProp] === '0.0001ms') {
1774
+ self.wrapperStyle[durationProp] = '0s';
1775
+ }
1776
+ });
1777
+ }
1778
+ this.wrapperStyle.opacity = '0';
1779
+ }
1780
+ }
1781
+
1782
+ Indicator.prototype = {
1783
+ handleEvent: function (e) {
1784
+ switch ( e.type ) {
1785
+ case 'touchstart':
1786
+ case 'pointerdown':
1787
+ case 'MSPointerDown':
1788
+ case 'mousedown':
1789
+ this._start(e);
1790
+ break;
1791
+ case 'touchmove':
1792
+ case 'pointermove':
1793
+ case 'MSPointerMove':
1794
+ case 'mousemove':
1795
+ this._move(e);
1796
+ break;
1797
+ case 'touchend':
1798
+ case 'pointerup':
1799
+ case 'MSPointerUp':
1800
+ case 'mouseup':
1801
+ case 'touchcancel':
1802
+ case 'pointercancel':
1803
+ case 'MSPointerCancel':
1804
+ case 'mousecancel':
1805
+ this._end(e);
1806
+ break;
1807
+ }
1808
+ },
1809
+
1810
+ destroy: function () {
1811
+ if ( this.options.fadeScrollbars ) {
1812
+ clearTimeout(this.fadeTimeout);
1813
+ this.fadeTimeout = null;
1814
+ }
1815
+ if ( this.options.interactive ) {
1816
+ utils.removeEvent(this.indicator, 'touchstart', this);
1817
+ utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
1818
+ utils.removeEvent(this.indicator, 'mousedown', this);
1819
+
1820
+ utils.removeEvent(window, 'touchmove', this);
1821
+ utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
1822
+ utils.removeEvent(window, 'mousemove', this);
1823
+
1824
+ utils.removeEvent(window, 'touchend', this);
1825
+ utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
1826
+ utils.removeEvent(window, 'mouseup', this);
1827
+ }
1828
+
1829
+ if ( this.options.defaultScrollbars ) {
1830
+ this.wrapper.parentNode.removeChild(this.wrapper);
1831
+ }
1832
+ },
1833
+
1834
+ _start: function (e) {
1835
+ var point = e.touches ? e.touches[0] : e;
1836
+
1837
+ e.preventDefault();
1838
+ e.stopPropagation();
1839
+
1840
+ this.transitionTime();
1841
+
1842
+ this.initiated = true;
1843
+ this.moved = false;
1844
+ this.lastPointX = point.pageX;
1845
+ this.lastPointY = point.pageY;
1846
+
1847
+ this.startTime = utils.getTime();
1848
+
1849
+ if ( !this.options.disableTouch ) {
1850
+ utils.addEvent(window, 'touchmove', this);
1851
+ }
1852
+ if ( !this.options.disablePointer ) {
1853
+ utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
1854
+ }
1855
+ if ( !this.options.disableMouse ) {
1856
+ utils.addEvent(window, 'mousemove', this);
1857
+ }
1858
+
1859
+ this.scroller._execEvent('beforeScrollStart');
1860
+ },
1861
+
1862
+ _move: function (e) {
1863
+ var point = e.touches ? e.touches[0] : e,
1864
+ deltaX, deltaY,
1865
+ newX, newY,
1866
+ timestamp = utils.getTime();
1867
+
1868
+ if ( !this.moved ) {
1869
+ this.scroller._execEvent('scrollStart');
1870
+ }
1871
+
1872
+ this.moved = true;
1873
+
1874
+ deltaX = point.pageX - this.lastPointX;
1875
+ this.lastPointX = point.pageX;
1876
+
1877
+ deltaY = point.pageY - this.lastPointY;
1878
+ this.lastPointY = point.pageY;
1879
+
1880
+ newX = this.x + deltaX;
1881
+ newY = this.y + deltaY;
1882
+
1883
+ this._pos(newX, newY);
1884
+
1885
+
1886
+ if ( this.scroller.options.probeType == 1 && timestamp - this.startTime > 300 ) {
1887
+ this.startTime = timestamp;
1888
+ this.scroller._execEvent('scroll');
1889
+ } else if ( this.scroller.options.probeType > 1 ) {
1890
+ this.scroller._execEvent('scroll');
1891
+ }
1892
+
1893
+
1894
+ // INSERT POINT: indicator._move
1895
+
1896
+ e.preventDefault();
1897
+ e.stopPropagation();
1898
+ },
1899
+
1900
+ _end: function (e) {
1901
+ if ( !this.initiated ) {
1902
+ return;
1903
+ }
1904
+
1905
+ this.initiated = false;
1906
+
1907
+ e.preventDefault();
1908
+ e.stopPropagation();
1909
+
1910
+ utils.removeEvent(window, 'touchmove', this);
1911
+ utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
1912
+ utils.removeEvent(window, 'mousemove', this);
1913
+
1914
+ if ( this.scroller.options.snap ) {
1915
+ var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
1916
+
1917
+ var time = this.options.snapSpeed || Math.max(
1918
+ Math.max(
1919
+ Math.min(Math.abs(this.scroller.x - snap.x), 1000),
1920
+ Math.min(Math.abs(this.scroller.y - snap.y), 1000)
1921
+ ), 300);
1922
+
1923
+ if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
1924
+ this.scroller.directionX = 0;
1925
+ this.scroller.directionY = 0;
1926
+ this.scroller.currentPage = snap;
1927
+ this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
1928
+ }
1929
+ }
1930
+
1931
+ if ( this.moved ) {
1932
+ this.scroller._execEvent('scrollEnd');
1933
+ }
1934
+ },
1935
+
1936
+ transitionTime: function (time) {
1937
+ time = time || 0;
1938
+ var durationProp = utils.style.transitionDuration;
1939
+ if(!durationProp) {
1940
+ return;
1941
+ }
1942
+
1943
+ this.indicatorStyle[durationProp] = time + 'ms';
1944
+
1945
+ if ( !time && utils.isBadAndroid ) {
1946
+ this.indicatorStyle[durationProp] = '0.0001ms';
1947
+ // remove 0.0001ms
1948
+ var self = this;
1949
+ rAF(function() {
1950
+ if(self.indicatorStyle[durationProp] === '0.0001ms') {
1951
+ self.indicatorStyle[durationProp] = '0s';
1952
+ }
1953
+ });
1954
+ }
1955
+ },
1956
+
1957
+ transitionTimingFunction: function (easing) {
1958
+ this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
1959
+ },
1960
+
1961
+ refresh: function () {
1962
+ this.transitionTime();
1963
+
1964
+ if ( this.options.listenX && !this.options.listenY ) {
1965
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
1966
+ } else if ( this.options.listenY && !this.options.listenX ) {
1967
+ this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
1968
+ } else {
1969
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
1970
+ }
1971
+
1972
+ if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
1973
+ utils.addClass(this.wrapper, 'iScrollBothScrollbars');
1974
+ utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
1975
+
1976
+ if ( this.options.defaultScrollbars && this.options.customStyle ) {
1977
+ if ( this.options.listenX ) {
1978
+ this.wrapper.style.right = '8px';
1979
+ } else {
1980
+ this.wrapper.style.bottom = '8px';
1981
+ }
1982
+ }
1983
+ } else {
1984
+ utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
1985
+ utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
1986
+
1987
+ if ( this.options.defaultScrollbars && this.options.customStyle ) {
1988
+ if ( this.options.listenX ) {
1989
+ this.wrapper.style.right = '2px';
1990
+ } else {
1991
+ this.wrapper.style.bottom = '2px';
1992
+ }
1993
+ }
1994
+ }
1995
+
1996
+ var r = this.wrapper.offsetHeight; // force refresh
1997
+
1998
+ if ( this.options.listenX ) {
1999
+ this.wrapperWidth = this.wrapper.clientWidth;
2000
+ if ( this.options.resize ) {
2001
+ this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 32);
2002
+ this.indicatorStyle.width = this.indicatorWidth + 'px';
2003
+ } else {
2004
+ this.indicatorWidth = this.indicator.clientWidth;
2005
+ }
2006
+
2007
+ this.maxPosX = this.wrapperWidth - this.indicatorWidth;
2008
+
2009
+ if ( this.options.shrink == 'clip' ) {
2010
+ this.minBoundaryX = -this.indicatorWidth + 8;
2011
+ this.maxBoundaryX = this.wrapperWidth - 8;
2012
+ } else {
2013
+ this.minBoundaryX = 0;
2014
+ this.maxBoundaryX = this.maxPosX;
2015
+ }
2016
+
2017
+ this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
2018
+ }
2019
+
2020
+ if ( this.options.listenY ) {
2021
+ this.wrapperHeight = this.wrapper.clientHeight;
2022
+ if ( this.options.resize ) {
2023
+ this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 32);
2024
+ this.indicatorStyle.height = this.indicatorHeight + 'px';
2025
+ } else {
2026
+ this.indicatorHeight = this.indicator.clientHeight;
2027
+ }
2028
+
2029
+ this.maxPosY = this.wrapperHeight - this.indicatorHeight;
2030
+
2031
+ if ( this.options.shrink == 'clip' ) {
2032
+ this.minBoundaryY = -this.indicatorHeight + 8;
2033
+ this.maxBoundaryY = this.wrapperHeight - 8;
2034
+ } else {
2035
+ this.minBoundaryY = 0;
2036
+ this.maxBoundaryY = this.maxPosY;
2037
+ }
2038
+
2039
+ this.maxPosY = this.wrapperHeight - this.indicatorHeight;
2040
+ this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
2041
+ }
2042
+
2043
+ this.updatePosition();
2044
+ },
2045
+
2046
+ updatePosition: function () {
2047
+ var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
2048
+ y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
2049
+
2050
+ if ( !this.options.ignoreBoundaries ) {
2051
+ if ( x < this.minBoundaryX ) {
2052
+ if ( this.options.shrink == 'scale' ) {
2053
+ this.width = Math.max(this.indicatorWidth + x, 8);
2054
+ this.indicatorStyle.width = this.width + 'px';
2055
+ }
2056
+ x = this.minBoundaryX;
2057
+ } else if ( x > this.maxBoundaryX ) {
2058
+ if ( this.options.shrink == 'scale' ) {
2059
+ this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
2060
+ this.indicatorStyle.width = this.width + 'px';
2061
+ x = this.maxPosX + this.indicatorWidth - this.width;
2062
+ } else {
2063
+ x = this.maxBoundaryX;
2064
+ }
2065
+ } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
2066
+ this.width = this.indicatorWidth;
2067
+ this.indicatorStyle.width = this.width + 'px';
2068
+ }
2069
+
2070
+ if ( y < this.minBoundaryY ) {
2071
+ if ( this.options.shrink == 'scale' ) {
2072
+ this.height = Math.max(this.indicatorHeight + y * 3, 8);
2073
+ this.indicatorStyle.height = this.height + 'px';
2074
+ }
2075
+ y = this.minBoundaryY;
2076
+ } else if ( y > this.maxBoundaryY ) {
2077
+ if ( this.options.shrink == 'scale' ) {
2078
+ this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
2079
+ this.indicatorStyle.height = this.height + 'px';
2080
+ y = this.maxPosY + this.indicatorHeight - this.height;
2081
+ } else {
2082
+ y = this.maxBoundaryY;
2083
+ }
2084
+ } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
2085
+ this.height = this.indicatorHeight;
2086
+ this.indicatorStyle.height = this.height + 'px';
2087
+ }
2088
+ }
2089
+
2090
+ this.x = x;
2091
+ this.y = y;
2092
+
2093
+ if ( this.scroller.options.useTransform ) {
2094
+ this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
2095
+ } else {
2096
+ this.indicatorStyle.left = x + 'px';
2097
+ this.indicatorStyle.top = y + 'px';
2098
+ }
2099
+ },
2100
+
2101
+ _pos: function (x, y) {
2102
+ if ( x < 0 ) {
2103
+ x = 0;
2104
+ } else if ( x > this.maxPosX ) {
2105
+ x = this.maxPosX;
2106
+ }
2107
+
2108
+ if ( y < 0 ) {
2109
+ y = 0;
2110
+ } else if ( y > this.maxPosY ) {
2111
+ y = this.maxPosY;
2112
+ }
2113
+
2114
+ x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
2115
+ y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
2116
+
2117
+ this.scroller.scrollTo(x, y);
2118
+ },
2119
+
2120
+ fade: function (val, hold) {
2121
+ if ( hold && !this.visible ) {
2122
+ return;
2123
+ }
2124
+
2125
+ clearTimeout(this.fadeTimeout);
2126
+ this.fadeTimeout = null;
2127
+
2128
+ var time = val ? 250 : 500,
2129
+ delay = val ? 0 : 300;
2130
+
2131
+ val = val ? '1' : '0';
2132
+
2133
+ this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
2134
+
2135
+ this.fadeTimeout = setTimeout((function (val) {
2136
+ this.wrapperStyle.opacity = val;
2137
+ this.visible = +val;
2138
+ }).bind(this, val), delay);
2139
+ }
2140
+ };
2141
+
2142
+ IScroll.utils = utils;
2143
+
2144
+ return IScroll;
2145
+
2146
+ // if ( typeof module != 'undefined' && module.exports ) {
2147
+ // module.exports = IScroll;
2148
+ // } else if ( typeof define == 'function' && define.amd ) {
2149
+ // define( function () { return IScroll; } );
2150
+ // } else {
2151
+ // window.IScroll = IScroll;
2152
+ // }
2153
+
2154
+ })(window, document, Math);