mui_app_rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +34 -0
  3. data/app/assets/fonts/mui.ttf +0 -0
  4. data/app/assets/javascripts/mui_app_rails/actions.js +26 -0
  5. data/app/assets/javascripts/mui_app_rails/ajax.plugin.js +3 -0
  6. data/app/assets/javascripts/mui_app_rails/input.plugin.js +232 -0
  7. data/app/assets/javascripts/mui_app_rails/modals.js +37 -0
  8. data/app/assets/javascripts/mui_app_rails/mui.active.js +30 -0
  9. data/app/assets/javascripts/mui_app_rails/mui.ajax.5+.js +27 -0
  10. data/app/assets/javascripts/mui_app_rails/mui.ajax.js +277 -0
  11. data/app/assets/javascripts/mui_app_rails/mui.animation.js +39 -0
  12. data/app/assets/javascripts/mui_app_rails/mui.animationframe.js +72 -0
  13. data/app/assets/javascripts/mui_app_rails/mui.back.5+.js +108 -0
  14. data/app/assets/javascripts/mui_app_rails/mui.back.js +56 -0
  15. data/app/assets/javascripts/mui_app_rails/mui.class.js +40 -0
  16. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.js +894 -0
  17. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.pullrefresh.js +150 -0
  18. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.slider.js +361 -0
  19. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.slider.old.js +332 -0
  20. data/app/assets/javascripts/mui_app_rails/mui.detect.5+.js +18 -0
  21. data/app/assets/javascripts/mui_app_rails/mui.detect.js +50 -0
  22. data/app/assets/javascripts/mui_app_rails/mui.dialog.alert.js +27 -0
  23. data/app/assets/javascripts/mui_app_rails/mui.dialog.confirm.js +27 -0
  24. data/app/assets/javascripts/mui_app_rails/mui.dialog.prompt.js +33 -0
  25. data/app/assets/javascripts/mui_app_rails/mui.dialog.toast.js +20 -0
  26. data/app/assets/javascripts/mui_app_rails/mui.event.js +160 -0
  27. data/app/assets/javascripts/mui_app_rails/mui.fixed.animation.js +22 -0
  28. data/app/assets/javascripts/mui_app_rails/mui.fixed.classlist.js +50 -0
  29. data/app/assets/javascripts/mui_app_rails/mui.fixed.fastclick.js +64 -0
  30. data/app/assets/javascripts/mui_app_rails/mui.fixed.js +40 -0
  31. data/app/assets/javascripts/mui_app_rails/mui.fixed.keyboard.js +56 -0
  32. data/app/assets/javascripts/mui_app_rails/mui.gestures.drag.js +48 -0
  33. data/app/assets/javascripts/mui_app_rails/mui.gestures.flick.js +30 -0
  34. data/app/assets/javascripts/mui_app_rails/mui.gestures.hold.js +41 -0
  35. data/app/assets/javascripts/mui_app_rails/mui.gestures.js +207 -0
  36. data/app/assets/javascripts/mui_app_rails/mui.gestures.longtap.js +43 -0
  37. data/app/assets/javascripts/mui_app_rails/mui.gestures.swipe.js +29 -0
  38. data/app/assets/javascripts/mui_app_rails/mui.gestures.tap.js +40 -0
  39. data/app/assets/javascripts/mui_app_rails/mui.init.5+.js +441 -0
  40. data/app/assets/javascripts/mui_app_rails/mui.init.js +100 -0
  41. data/app/assets/javascripts/mui_app_rails/mui.init.pullrefresh.js +57 -0
  42. data/app/assets/javascripts/mui_app_rails/mui.js +396 -0
  43. data/app/assets/javascripts/mui_app_rails/mui.jsonp.js +108 -0
  44. data/app/assets/javascripts/mui_app_rails/mui.layout.js +22 -0
  45. data/app/assets/javascripts/mui_app_rails/mui.namespace.js +35 -0
  46. data/app/assets/javascripts/mui_app_rails/mui.number.js +93 -0
  47. data/app/assets/javascripts/mui_app_rails/mui.offcanvas.js +497 -0
  48. data/app/assets/javascripts/mui_app_rails/mui.pullrefresh.js +157 -0
  49. data/app/assets/javascripts/mui_app_rails/mui.target.js +58 -0
  50. data/app/assets/javascripts/mui_app_rails/mui.view.js +172 -0
  51. data/app/assets/javascripts/mui_app_rails/popovers.js +278 -0
  52. data/app/assets/javascripts/mui_app_rails/pullrefresh.5+.js +238 -0
  53. data/app/assets/javascripts/mui_app_rails/push.js +479 -0
  54. data/app/assets/javascripts/mui_app_rails/segmented-controllers.js +99 -0
  55. data/app/assets/javascripts/mui_app_rails/sliders.js +362 -0
  56. data/app/assets/javascripts/mui_app_rails/switches.js +165 -0
  57. data/app/assets/javascripts/mui_app_rails/tableviews.js +512 -0
  58. data/app/assets/javascripts/mui_app_rails.js +1 -0
  59. data/app/assets/stylesheets/mui_app_rails/badges.scss +88 -0
  60. data/app/assets/stylesheets/mui_app_rails/bars.scss +312 -0
  61. data/app/assets/stylesheets/mui_app_rails/base.scss +196 -0
  62. data/app/assets/stylesheets/mui_app_rails/buttons.scss +205 -0
  63. data/app/assets/stylesheets/mui_app_rails/cards.scss +62 -0
  64. data/app/assets/stylesheets/mui_app_rails/forms.scss +452 -0
  65. data/app/assets/stylesheets/mui_app_rails/fullscreen.scss +35 -0
  66. data/app/assets/stylesheets/mui_app_rails/grid.scss +75 -0
  67. data/app/assets/stylesheets/mui_app_rails/hack.scss +14 -0
  68. data/app/assets/stylesheets/mui_app_rails/icon.scss +170 -0
  69. data/app/assets/stylesheets/mui_app_rails/iscroll.scss +43 -0
  70. data/app/assets/stylesheets/mui_app_rails/loadings.scss +111 -0
  71. data/app/assets/stylesheets/mui_app_rails/mixins.scss +212 -0
  72. data/app/assets/stylesheets/mui_app_rails/modals.scss +34 -0
  73. data/app/assets/stylesheets/mui_app_rails/mui.scss +46 -0
  74. data/app/assets/stylesheets/mui_app_rails/normalize.scss +425 -0
  75. data/app/assets/stylesheets/mui_app_rails/number.scss +70 -0
  76. data/app/assets/stylesheets/mui_app_rails/off-canvas.scss +84 -0
  77. data/app/assets/stylesheets/mui_app_rails/os.scss +12 -0
  78. data/app/assets/stylesheets/mui_app_rails/pagination.scss +155 -0
  79. data/app/assets/stylesheets/mui_app_rails/popovers.scss +198 -0
  80. data/app/assets/stylesheets/mui_app_rails/pullrefreshs.scss +98 -0
  81. data/app/assets/stylesheets/mui_app_rails/push.scss +63 -0
  82. data/app/assets/stylesheets/mui_app_rails/scroll.scss +95 -0
  83. data/app/assets/stylesheets/mui_app_rails/segmented-controls.scss +150 -0
  84. data/app/assets/stylesheets/mui_app_rails/slider-cell.scss +20 -0
  85. data/app/assets/stylesheets/mui_app_rails/sliders.scss +133 -0
  86. data/app/assets/stylesheets/mui_app_rails/switches.scss +115 -0
  87. data/app/assets/stylesheets/mui_app_rails/table-views.scss +482 -0
  88. data/app/assets/stylesheets/mui_app_rails/toast.scss +16 -0
  89. data/app/assets/stylesheets/mui_app_rails/type.scss +23 -0
  90. data/app/assets/stylesheets/mui_app_rails/variables.scss +64 -0
  91. data/app/assets/stylesheets/mui_app_rails.css +3 -0
  92. data/lib/mui_app_rails/engine.rb +5 -0
  93. data/lib/mui_app_rails/version.rb +3 -0
  94. data/lib/mui_app_rails.rb +5 -0
  95. metadata +179 -0
@@ -0,0 +1,894 @@
1
+ (function($, window, document, undefined) {
2
+ var CLASS_SCROLLBAR = $.className('scrollbar');
3
+ var CLASS_INDICATOR = $.className('scrollbar-indicator');
4
+ var CLASS_SCROLLBAR_VERTICAL = CLASS_SCROLLBAR + '-vertical';
5
+ var CLASS_SCROLLBAR_HORIZONTAL = CLASS_SCROLLBAR + '-horizontal';
6
+
7
+ var CLASS_ACTIVE = $.className('active');
8
+
9
+ var ease = {
10
+ quadratic: {
11
+ style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
12
+ fn: function(k) {
13
+ return k * (2 - k);
14
+ }
15
+ },
16
+ circular: {
17
+ style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',
18
+ fn: function(k) {
19
+ return Math.sqrt(1 - (--k * k));
20
+ }
21
+ }
22
+ }
23
+ var Scroll = $.Class.extend({
24
+ init: function(element, options) {
25
+ this.wrapper = this.element = element;
26
+ this.scroller = this.wrapper.children[0];
27
+ this.scrollerStyle = this.scroller && this.scroller.style;
28
+ this.stopped = false;
29
+
30
+ this.options = $.extend(true, {
31
+ scrollY: true,
32
+ scrollX: false,
33
+ startX: 0,
34
+ startY: 0,
35
+ indicators: true,
36
+ stopPropagation: false,
37
+ hardwareAccelerated: true,
38
+ fixedBadAndorid: false,
39
+ preventDefaultException: {
40
+ tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/
41
+ },
42
+ momentum: true,
43
+
44
+ snap: false,
45
+
46
+ bounce: true,
47
+ bounceTime: 300,
48
+ bounceEasing: ease.circular.style,
49
+
50
+ directionLockThreshold: 5,
51
+
52
+ parallaxElement: false,
53
+ parallaxRatio: 0.5
54
+ }, options);
55
+
56
+ this.x = 0;
57
+ this.y = 0;
58
+ this.translateZ = this.options.hardwareAccelerated ? ' translateZ(0)' : '';
59
+
60
+ this._init();
61
+ if (this.scroller) {
62
+ this.refresh();
63
+ // if (this.options.startX !== 0 || this.options.startY !== 0) { //需要判断吗?后续根据实际情况再看看
64
+ this.scrollTo(this.options.startX, this.options.startY);
65
+ // }
66
+ }
67
+ },
68
+ _init: function() {
69
+ this._initParallax();
70
+ this._initIndicators();
71
+ this._initEvent();
72
+ },
73
+ _initParallax: function() {
74
+ if (this.options.parallaxElement) {
75
+ this.parallaxElement = document.querySelector(this.options.parallaxElement);
76
+ this.parallaxStyle = this.parallaxElement.style;
77
+ this.parallaxHeight = this.parallaxElement.offsetHeight;
78
+ this.parallaxImgStyle = this.parallaxElement.querySelector('img').style;
79
+ }
80
+ },
81
+ _initIndicators: function() {
82
+ var self = this;
83
+ self.indicators = [];
84
+ if (!this.options.indicators) {
85
+ return;
86
+ }
87
+ var indicators = [],
88
+ indicator;
89
+
90
+ // Vertical scrollbar
91
+ if (self.options.scrollY) {
92
+ indicator = {
93
+ el: this._createScrollBar(CLASS_SCROLLBAR_VERTICAL),
94
+ listenX: false
95
+ };
96
+
97
+ this.wrapper.appendChild(indicator.el);
98
+ indicators.push(indicator);
99
+ }
100
+
101
+ // Horizontal scrollbar
102
+ if (this.options.scrollX) {
103
+ indicator = {
104
+ el: this._createScrollBar(CLASS_SCROLLBAR_HORIZONTAL),
105
+ listenY: false
106
+ };
107
+
108
+ this.wrapper.appendChild(indicator.el);
109
+ indicators.push(indicator);
110
+ }
111
+
112
+ for (var i = indicators.length; i--;) {
113
+ this.indicators.push(new Indicator(this, indicators[i]));
114
+ }
115
+
116
+ this.wrapper.addEventListener('scrollend', function() {
117
+ self.indicators.map(function(indicator) {
118
+ indicator.fade();
119
+ });
120
+ });
121
+
122
+ this.wrapper.addEventListener('scrollstart', function() {
123
+ self.indicators.map(function(indicator) {
124
+ indicator.fade(1);
125
+ });
126
+ });
127
+
128
+ // this.wrapper.addEventListener('beforescrollstart', function() {
129
+ // self.indicators.map(function(indicator) {
130
+ // indicator.fade(1, true);
131
+ // });
132
+ // });
133
+
134
+ this.wrapper.addEventListener('refresh', function() {
135
+ self.indicators.map(function(indicator) {
136
+ indicator.refresh();
137
+ });
138
+ });
139
+ },
140
+ _initSnap: function() {
141
+ this.currentPage = {};
142
+ this.pages = [];
143
+ var snaps = this.snaps;
144
+ var length = snaps.length;
145
+ var m = 0;
146
+ var n = -1;
147
+ var x = 0;
148
+ var cx = 0;
149
+ for (var i = 0; i < length; i++) {
150
+ var snap = snaps[i];
151
+ var offsetLeft = snap.offsetLeft;
152
+ var offsetWidth = snap.offsetWidth;
153
+ if (i === 0 || offsetLeft <= snaps[i - 1].offsetLeft) {
154
+ m = 0;
155
+ n++;
156
+ }
157
+ if (!this.pages[m]) {
158
+ this.pages[m] = [];
159
+ }
160
+ x = this._getSnapX(offsetLeft);
161
+ cx = x - Math.round((offsetWidth) / 2);
162
+ this.pages[m][n] = {
163
+ x: x,
164
+ cx: cx,
165
+ pageX: m,
166
+ element: snap
167
+ }
168
+ if (snap.classList.contains(CLASS_ACTIVE)) {
169
+ this.currentPage = this.pages[m][0];
170
+ }
171
+ if (x >= this.maxScrollX) {
172
+ m++;
173
+ }
174
+ }
175
+ this.options.startX = this.currentPage.x || 0;
176
+ },
177
+ _getSnapX: function(offsetLeft) {
178
+ return Math.max(Math.min(0, -offsetLeft + (this.wrapperWidth / 2)), this.maxScrollX);
179
+ },
180
+ _gotoPage: function(index) {
181
+ this.currentPage = this.pages[Math.min(index, this.pages.length - 1)][0];
182
+ for (var i = 0, len = this.snaps.length; i < len; i++) {
183
+ if (i === index) {
184
+ this.snaps[i].classList.add(CLASS_ACTIVE);
185
+ } else {
186
+ this.snaps[i].classList.remove(CLASS_ACTIVE);
187
+ }
188
+ }
189
+ this.scrollTo(this.currentPage.x, 0, this.options.bounceTime);
190
+ },
191
+ _nearestSnap: function(x) {
192
+ if (!this.pages.length) {
193
+ return {
194
+ x: 0,
195
+ pageX: 0
196
+ };
197
+ }
198
+ var i = 0;
199
+ var length = this.pages.length;
200
+
201
+ if (x > 0) {
202
+ x = 0;
203
+ } else if (x < this.maxScrollX) {
204
+ x = this.maxScrollX;
205
+ }
206
+
207
+ for (; i < length; i++) {
208
+ if (x >= this.pages[i][0].cx) {
209
+ return this.pages[i][0];
210
+ }
211
+ }
212
+ return {
213
+ x: 0,
214
+ pageX: 0
215
+ };
216
+ },
217
+ _initEvent: function() {
218
+ window.addEventListener('orientationchange', this);
219
+ window.addEventListener('resize', this);
220
+
221
+ this.scroller.addEventListener('webkitTransitionEnd', this);
222
+
223
+ this.wrapper.addEventListener('touchstart', this);
224
+ this.wrapper.addEventListener('touchcancel', this);
225
+ this.wrapper.addEventListener('touchend', this);
226
+ this.wrapper.addEventListener('drag', this);
227
+ this.wrapper.addEventListener('dragend', this);
228
+ this.wrapper.addEventListener('flick', this);
229
+ this.wrapper.addEventListener('scrollend', this);
230
+ if (this.options.scrollX) {
231
+ this.wrapper.addEventListener('swiperight', this);
232
+ }
233
+ var segmentedControl = this.wrapper.querySelector($.classSelector('.segmented-control'));
234
+ if (segmentedControl) { //靠,这个bug排查了一下午,阻止hash跳转,一旦hash跳转会导致可拖拽选项卡的tab不见
235
+ mui(segmentedControl).on('click', 'a', $.preventDefault);
236
+ }
237
+ },
238
+ handleEvent: function(e) {
239
+ if (this.stopped) {
240
+ this.resetPosition();
241
+ return;
242
+ }
243
+
244
+ switch (e.type) {
245
+ case 'touchstart':
246
+ this._start(e);
247
+ break;
248
+ case 'drag':
249
+ this.options.stopPropagation && e.stopPropagation();
250
+ this._drag(e);
251
+ break;
252
+ case 'dragend':
253
+ case 'flick':
254
+ this.options.stopPropagation && e.stopPropagation();
255
+ this._flick(e);
256
+ break;
257
+ case 'touchcancel':
258
+ case 'touchend':
259
+ this._end(e);
260
+ break;
261
+ case 'webkitTransitionEnd':
262
+ this._transitionEnd(e);
263
+ break;
264
+ case 'scrollend':
265
+ this._scrollend(e);
266
+ e.stopPropagation();
267
+ break;
268
+ case 'orientationchange':
269
+ case 'resize':
270
+ this._resize();
271
+ break;
272
+ case 'swiperight':
273
+ e.stopPropagation();
274
+ break;
275
+
276
+ }
277
+ },
278
+ _start: function(e) {
279
+ this.moved = this.needReset = false;
280
+ this._transitionTime();
281
+ if (this.isInTransition) {
282
+ this.needReset = true;
283
+ this.isInTransition = false;
284
+ var pos = $.parseTranslateMatrix($.getStyles(this.scroller, 'webkitTransform'));
285
+ this.setTranslate(Math.round(pos.x), Math.round(pos.y));
286
+ this.resetPosition(); //reset
287
+ $.trigger(this.scroller, 'scrollend', this);
288
+ // e.stopPropagation();
289
+ e.preventDefault();
290
+ }
291
+ this.reLayout();
292
+ $.trigger(this.scroller, 'beforescrollstart', this);
293
+ },
294
+ _getDirectionByAngle: function(angle) {
295
+ if (angle < -80 && angle > -100) {
296
+ return 'up';
297
+ } else if (angle >= 80 && angle < 100) {
298
+ return 'down';
299
+ } else if (angle >= 170 || angle <= -170) {
300
+ return 'left';
301
+ } else if (angle >= -35 && angle <= 10) {
302
+ return 'right';
303
+ }
304
+ return null;
305
+ },
306
+ _drag: function(e) {
307
+ // if (this.needReset) {
308
+ // e.stopPropagation(); //disable parent drag(nested scroller)
309
+ // return;
310
+ // }
311
+ var detail = e.detail;
312
+ if (this.options.scrollY || detail.direction === 'up' || detail.direction === 'down') { //如果是竖向滚动或手势方向是上或下
313
+ //ios8 hack
314
+ if ($.os.ios && parseFloat($.os.version) >= 8) { //多webview时,离开当前webview会导致后续touch事件不触发
315
+ var clientY = detail.gesture.touches[0].clientY;
316
+ //下拉刷新 or 上拉加载
317
+ if ((clientY + 10) > window.innerHeight || clientY < 10) {
318
+ this.resetPosition(this.options.bounceTime);
319
+ return;
320
+ }
321
+ }
322
+ }
323
+ var isPreventDefault = isReturn = false;
324
+ var direction = this._getDirectionByAngle(detail.angle);
325
+ if (detail.direction === 'left' || detail.direction === 'right') {
326
+ if (this.options.scrollX) {
327
+ isPreventDefault = true;
328
+ if (!this.moved) { //识别角度(该角度导致轮播不灵敏)
329
+ // if (direction !== 'left' && direction !== 'right') {
330
+ // isReturn = true;
331
+ // } else {
332
+ $.gestures.touch.lockDirection = true; //锁定方向
333
+ $.gestures.touch.startDirection = detail.direction;
334
+ // }
335
+ }
336
+ } else if (this.options.scrollY && !this.moved) {
337
+ isReturn = true;
338
+ }
339
+ } else if (detail.direction === 'up' || detail.direction === 'down') {
340
+ if (this.options.scrollY) {
341
+ isPreventDefault = true;
342
+ // if (!this.moved) { //识别角度,竖向滚动似乎没必要进行小角度验证
343
+ // if (direction !== 'up' && direction !== 'down') {
344
+ // isReturn = true;
345
+ // }
346
+ // }
347
+ if (!this.moved) {
348
+ $.gestures.touch.lockDirection = true; //锁定方向
349
+ $.gestures.touch.startDirection = detail.direction;
350
+ }
351
+ } else if (this.options.scrollX && !this.moved) {
352
+ isReturn = true;
353
+ }
354
+ } else {
355
+ isReturn = true;
356
+ }
357
+ if (isPreventDefault) {
358
+ e.stopPropagation(); //阻止冒泡(scroll类嵌套)
359
+ detail.gesture && detail.gesture.preventDefault();
360
+ }
361
+ if (isReturn) { //禁止非法方向滚动
362
+ return;
363
+ }
364
+ if (!this.moved) {
365
+ $.trigger(this.scroller, 'scrollstart', this);
366
+ } else {
367
+ e.stopPropagation(); //move期间阻止冒泡(scroll嵌套)
368
+ }
369
+ var deltaX = 0;
370
+ var deltaY = 0;
371
+ if (!this.moved) { //start
372
+ deltaX = detail.deltaX;
373
+ deltaY = detail.deltaY;
374
+ } else { //move
375
+ deltaX = detail.deltaX - detail.lastDeltaX;
376
+ deltaY = detail.deltaY - detail.lastDeltaY;
377
+ }
378
+ var absDeltaX = Math.abs(detail.deltaX);
379
+ var absDeltaY = Math.abs(detail.deltaY);
380
+ if (absDeltaX > absDeltaY + this.options.directionLockThreshold) {
381
+ deltaY = 0;
382
+ } else if (absDeltaY >= absDeltaX + this.options.directionLockThreshold) {
383
+ deltaX = 0;
384
+ }
385
+
386
+ deltaX = this.hasHorizontalScroll ? deltaX : 0;
387
+ deltaY = this.hasVerticalScroll ? deltaY : 0;
388
+ var newX = this.x + deltaX;
389
+ var newY = this.y + deltaY;
390
+ // Slow down if outside of the boundaries
391
+ if (newX > 0 || newX < this.maxScrollX) {
392
+ newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
393
+ }
394
+ if (newY > 0 || newY < this.maxScrollY) {
395
+ newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
396
+ }
397
+
398
+ if (!this.requestAnimationFrame) {
399
+ this._updateTranslate();
400
+ }
401
+
402
+ this.moved = true;
403
+ this.x = newX;
404
+ this.y = newY;
405
+ $.trigger(this.scroller, 'scroll', this);
406
+ },
407
+ _flick: function(e) {
408
+ // if (!this.moved || this.needReset) {
409
+ // return;
410
+ // }
411
+ if (!this.moved) {
412
+ return;
413
+ }
414
+ e.stopPropagation();
415
+ var detail = e.detail;
416
+ this._clearRequestAnimationFrame();
417
+ if (e.type === 'dragend' && detail.flick) { //dragend
418
+ return;
419
+ }
420
+
421
+ var newX = Math.round(this.x);
422
+ var newY = Math.round(this.y);
423
+
424
+ this.isInTransition = false;
425
+ // reset if we are outside of the boundaries
426
+ if (this.resetPosition(this.options.bounceTime)) {
427
+ return;
428
+ }
429
+
430
+ this.scrollTo(newX, newY); // ensures that the last position is rounded
431
+
432
+ if (e.type === 'dragend') { //dragend
433
+ $.trigger(this.scroller, 'scrollend', this);
434
+ return;
435
+ }
436
+ var time = 0;
437
+ var easing = '';
438
+ // start momentum animation if needed
439
+ if (this.options.momentum && detail.flickTime < 300) {
440
+ momentumX = this.hasHorizontalScroll ? this._momentum(this.x, detail.flickDistanceX, detail.flickTime, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {
441
+ destination: newX,
442
+ duration: 0
443
+ };
444
+ momentumY = this.hasVerticalScroll ? this._momentum(this.y, detail.flickDistanceY, detail.flickTime, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {
445
+ destination: newY,
446
+ duration: 0
447
+ };
448
+ newX = momentumX.destination;
449
+ newY = momentumY.destination;
450
+ time = Math.max(momentumX.duration, momentumY.duration);
451
+ this.isInTransition = true;
452
+ }
453
+
454
+ if (newX != this.x || newY != this.y) {
455
+ if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {
456
+ easing = ease.quadratic;
457
+ }
458
+ this.scrollTo(newX, newY, time, easing);
459
+ return;
460
+ }
461
+
462
+ $.trigger(this.scroller, 'scrollend', this);
463
+ // e.stopPropagation();
464
+ },
465
+ _end: function(e) {
466
+ this.needReset = false;
467
+ if ((!this.moved && this.needReset) || e.type === 'touchcancel') {
468
+ this.resetPosition();
469
+ }
470
+ },
471
+ _transitionEnd: function(e) {
472
+ if (e.target != this.scroller || !this.isInTransition) {
473
+ return;
474
+ }
475
+ this._transitionTime();
476
+ if (!this.resetPosition(this.options.bounceTime)) {
477
+ this.isInTransition = false;
478
+ $.trigger(this.scroller, 'scrollend', this);
479
+ }
480
+ },
481
+ _scrollend: function(e) {
482
+ if (Math.abs(this.y) > 0 && this.y <= this.maxScrollY) {
483
+ $.trigger(this.scroller, 'scrollbottom', this);
484
+ }
485
+ },
486
+ _resize: function() {
487
+ var that = this;
488
+ clearTimeout(that.resizeTimeout);
489
+ that.resizeTimeout = setTimeout(function() {
490
+ that.refresh();
491
+ }, that.options.resizePolling);
492
+ },
493
+ _transitionTime: function(time) {
494
+ time = time || 0;
495
+ this.scrollerStyle['webkitTransitionDuration'] = time + 'ms';
496
+ if (this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
497
+ this.parallaxStyle['webkitTransitionDuration'] = time + 'ms';
498
+ }
499
+ if (this.options.fixedBadAndorid && !time && $.os.isBadAndroid) {
500
+ this.scrollerStyle['webkitTransitionDuration'] = '0.001s';
501
+ if (this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
502
+ this.parallaxStyle['webkitTransitionDuration'] = '0.001s';
503
+ }
504
+ }
505
+ if (this.indicators) {
506
+ for (var i = this.indicators.length; i--;) {
507
+ this.indicators[i].transitionTime(time);
508
+ }
509
+ }
510
+ },
511
+ _transitionTimingFunction: function(easing) {
512
+ this.scrollerStyle['webkitTransitionTimingFunction'] = easing;
513
+ if (this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
514
+ this.parallaxStyle['webkitTransitionDuration'] = easing;
515
+ }
516
+ if (this.indicators) {
517
+ for (var i = this.indicators.length; i--;) {
518
+ this.indicators[i].transitionTimingFunction(easing);
519
+ }
520
+ }
521
+ },
522
+ _translate: function(x, y) {
523
+ this.x = x;
524
+ this.y = y;
525
+ },
526
+ _clearRequestAnimationFrame: function() {
527
+ if (this.requestAnimationFrame) {
528
+ cancelAnimationFrame(this.requestAnimationFrame);
529
+ this.requestAnimationFrame = null;
530
+ }
531
+ },
532
+ _updateTranslate: function() {
533
+ var self = this;
534
+ if (self.x !== self.lastX || self.y !== self.lastY) {
535
+ self.setTranslate(self.x, self.y);
536
+ }
537
+ self.requestAnimationFrame = requestAnimationFrame(function() {
538
+ self._updateTranslate();
539
+ });
540
+ },
541
+ _createScrollBar: function(clazz) {
542
+ var scrollbar = document.createElement('div');
543
+ var indicator = document.createElement('div');
544
+ scrollbar.className = CLASS_SCROLLBAR + ' ' + clazz;
545
+ indicator.className = CLASS_INDICATOR;
546
+ scrollbar.appendChild(indicator);
547
+ if (clazz === CLASS_SCROLLBAR_VERTICAL) {
548
+ this.scrollbarY = scrollbar;
549
+ this.scrollbarIndicatorY = indicator;
550
+ } else if (clazz === CLASS_SCROLLBAR_HORIZONTAL) {
551
+ this.scrollbarX = scrollbar;
552
+ this.scrollbarIndicatorX = indicator;
553
+ }
554
+ this.wrapper.appendChild(scrollbar);
555
+ return scrollbar;
556
+ },
557
+ _preventDefaultException: function(el, exceptions) {
558
+ for (var i in exceptions) {
559
+ if (exceptions[i].test(el[i])) {
560
+ return true;
561
+ }
562
+ }
563
+ return false;
564
+ },
565
+ _reLayout: function() {
566
+ if (!this.hasHorizontalScroll) {
567
+ this.maxScrollX = 0;
568
+ this.scrollerWidth = this.wrapperWidth;
569
+ }
570
+
571
+ if (!this.hasVerticalScroll) {
572
+ this.maxScrollY = 0;
573
+ this.scrollerHeight = this.wrapperHeight;
574
+ }
575
+
576
+ this.indicators.map(function(indicator) {
577
+ indicator.refresh();
578
+ });
579
+
580
+ //以防slider类嵌套使用
581
+ if (this.options.snap && typeof this.options.snap === 'string') {
582
+ var items = this.scroller.querySelectorAll(this.options.snap);
583
+ this.itemLength = 0;
584
+ this.snaps = [];
585
+ for (var i = 0, len = items.length; i < len; i++) {
586
+ var item = items[i];
587
+ if (item.parentNode === this.scroller) {
588
+ this.itemLength++;
589
+ this.snaps.push(item);
590
+ }
591
+ }
592
+ this._initSnap(); //需要每次都_initSnap么。其实init的时候执行一次,后续resize的时候执行一次就行了吧.先这么做吧,如果影响性能,再调整
593
+ }
594
+ },
595
+ _momentum: function(current, distance, time, lowerMargin, wrapperSize, deceleration) {
596
+ var speed = parseFloat(Math.abs(distance) / time),
597
+ destination,
598
+ duration;
599
+
600
+ deceleration = deceleration === undefined ? 0.0006 : deceleration;
601
+ destination = current + (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);
602
+ duration = speed / deceleration;
603
+ if (destination < lowerMargin) {
604
+ destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;
605
+ distance = Math.abs(destination - current);
606
+ duration = distance / speed;
607
+ } else if (destination > 0) {
608
+ destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;
609
+ distance = Math.abs(current) + destination;
610
+ duration = distance / speed;
611
+ }
612
+
613
+ return {
614
+ destination: Math.round(destination),
615
+ duration: duration
616
+ };
617
+ },
618
+ _getTranslateStr: function(x, y) {
619
+ if (this.options.hardwareAccelerated) {
620
+ return 'translate3d(' + x + 'px,' + y + 'px,0px) ' + this.translateZ;
621
+ }
622
+ return 'translate(' + x + 'px,' + y + 'px) ';
623
+ },
624
+ //API
625
+ setStopped: function(stopped) {
626
+ this.stopped = !!stopped;
627
+ },
628
+ setTranslate: function(x, y) {
629
+ this.x = x;
630
+ this.y = y;
631
+ this.scrollerStyle['webkitTransform'] = this._getTranslateStr(x, y);
632
+ if (this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
633
+ var parallaxY = y * this.options.parallaxRatio;
634
+ var scale = 1 + parallaxY / ((this.parallaxHeight - parallaxY) / 2);
635
+ if (scale > 1) {
636
+ this.parallaxImgStyle['opacity'] = 1 - parallaxY / 100 * this.options.parallaxRatio;
637
+ this.parallaxStyle['webkitTransform'] = this._getTranslateStr(0, -parallaxY) + ' scale(' + scale + ',' + scale + ')';
638
+ } else {
639
+ this.parallaxImgStyle['opacity'] = 1;
640
+ this.parallaxStyle['webkitTransform'] = this._getTranslateStr(0, -1) + ' scale(1,1)';
641
+ }
642
+ }
643
+ if (this.indicators) {
644
+ for (var i = this.indicators.length; i--;) {
645
+ this.indicators[i].updatePosition();
646
+ }
647
+ }
648
+ this.lastX = this.x;
649
+ this.lastY = this.y;
650
+ },
651
+ reLayout: function() {
652
+ this.wrapper.offsetHeight;
653
+
654
+ var paddingLeft = parseFloat($.getStyles(this.wrapper, 'padding-left')) || 0;
655
+ var paddingRight = parseFloat($.getStyles(this.wrapper, 'padding-right')) || 0;
656
+ var paddingTop = parseFloat($.getStyles(this.wrapper, 'padding-top')) || 0;
657
+ var paddingBottom = parseFloat($.getStyles(this.wrapper, 'padding-bottom')) || 0;
658
+
659
+ var clientWidth = this.wrapper.clientWidth;
660
+ var clientHeight = this.wrapper.clientHeight;
661
+
662
+ this.scrollerWidth = this.scroller.offsetWidth;
663
+ this.scrollerHeight = this.scroller.offsetHeight;
664
+
665
+ this.wrapperWidth = clientWidth - paddingLeft - paddingRight;
666
+ this.wrapperHeight = clientHeight - paddingTop - paddingBottom;
667
+
668
+ this.maxScrollX = Math.min(this.wrapperWidth - this.scrollerWidth, 0);
669
+ this.maxScrollY = Math.min(this.wrapperHeight - this.scrollerHeight, 0);
670
+ this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
671
+ this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
672
+ this._reLayout();
673
+ },
674
+ resetPosition: function(time) {
675
+ var x = this.x,
676
+ y = this.y;
677
+
678
+ time = time || 0;
679
+ if (!this.hasHorizontalScroll || this.x > 0) {
680
+ x = 0;
681
+ } else if (this.x < this.maxScrollX) {
682
+ x = this.maxScrollX;
683
+ }
684
+
685
+ if (!this.hasVerticalScroll || this.y > 0) {
686
+ y = 0;
687
+ } else if (this.y < this.maxScrollY) {
688
+ y = this.maxScrollY;
689
+ }
690
+
691
+ if (x == this.x && y == this.y) {
692
+ return false;
693
+ }
694
+ this.scrollTo(x, y, time, this.options.bounceEasing);
695
+
696
+ return true;
697
+ },
698
+ refresh: function() {
699
+ this.reLayout();
700
+ $.trigger(this.scroller, 'refresh', this);
701
+ this.resetPosition();
702
+ },
703
+ scrollTo: function(x, y, time, easing) {
704
+ var easing = easing || ease.circular;
705
+ this.isInTransition = time > 0 && (this.lastX != x || this.lastY != y);
706
+ if (this.isInTransition) {
707
+ this._clearRequestAnimationFrame();
708
+ this._transitionTimingFunction(easing.style);
709
+ this._transitionTime(time);
710
+ this.setTranslate(x, y);
711
+ } else {
712
+ this.setTranslate(x, y);
713
+ }
714
+
715
+ },
716
+ scrollToBottom: function(time, easing) {
717
+ time = time || this.options.bounceTime;
718
+ this.scrollTo(0, this.maxScrollY, time, easing);
719
+ },
720
+ gotoPage: function(index) {
721
+ this._gotoPage(index);
722
+ }
723
+ });
724
+ //Indicator
725
+ var Indicator = function(scroller, options) {
726
+ this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
727
+ this.wrapperStyle = this.wrapper.style;
728
+ this.indicator = this.wrapper.children[0];
729
+ this.indicatorStyle = this.indicator.style;
730
+ this.scroller = scroller;
731
+
732
+ this.options = $.extend({
733
+ listenX: true,
734
+ listenY: true,
735
+ fade: false,
736
+ speedRatioX: 0,
737
+ speedRatioY: 0
738
+ }, options);
739
+
740
+
741
+ this.sizeRatioX = 1;
742
+ this.sizeRatioY = 1;
743
+ this.maxPosX = 0;
744
+ this.maxPosY = 0;
745
+
746
+ if (this.options.fade) {
747
+ this.wrapperStyle['webkitTransform'] = this.scroller.translateZ;
748
+ this.wrapperStyle['webkitTransitionDuration'] = this.options.fixedBadAndorid && $.os.isBadAndroid ? '0.001s' : '0ms';
749
+ this.wrapperStyle.opacity = '0';
750
+ }
751
+ }
752
+ Indicator.prototype = {
753
+ handleEvent: function(e) {
754
+
755
+ },
756
+ transitionTime: function(time) {
757
+ time = time || 0;
758
+ this.indicatorStyle['webkitTransitionDuration'] = time + 'ms';
759
+ if (this.scroller.options.fixedBadAndorid && !time && $.os.isBadAndroid) {
760
+ this.indicatorStyle['webkitTransitionDuration'] = '0.001s';
761
+ }
762
+ },
763
+ transitionTimingFunction: function(easing) {
764
+ this.indicatorStyle['webkitTransitionTimingFunction'] = easing;
765
+ },
766
+ refresh: function() {
767
+ this.transitionTime();
768
+
769
+ if (this.options.listenX && !this.options.listenY) {
770
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
771
+ } else if (this.options.listenY && !this.options.listenX) {
772
+ this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
773
+ } else {
774
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
775
+ }
776
+
777
+ this.wrapper.offsetHeight; // force refresh
778
+
779
+ if (this.options.listenX) {
780
+ this.wrapperWidth = this.wrapper.clientWidth;
781
+ this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
782
+ this.indicatorStyle.width = this.indicatorWidth + 'px';
783
+
784
+ this.maxPosX = this.wrapperWidth - this.indicatorWidth;
785
+
786
+ this.minBoundaryX = 0;
787
+ this.maxBoundaryX = this.maxPosX;
788
+
789
+ this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
790
+ }
791
+
792
+ if (this.options.listenY) {
793
+ this.wrapperHeight = this.wrapper.clientHeight;
794
+ this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
795
+ this.indicatorStyle.height = this.indicatorHeight + 'px';
796
+
797
+ this.maxPosY = this.wrapperHeight - this.indicatorHeight;
798
+
799
+ this.minBoundaryY = 0;
800
+ this.maxBoundaryY = this.maxPosY;
801
+
802
+ this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
803
+ }
804
+
805
+ this.updatePosition();
806
+ },
807
+
808
+ updatePosition: function() {
809
+ var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
810
+ y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
811
+
812
+ if (x < this.minBoundaryX) {
813
+ this.width = Math.max(this.indicatorWidth + x, 8);
814
+ this.indicatorStyle.width = this.width + 'px';
815
+ x = this.minBoundaryX;
816
+ } else if (x > this.maxBoundaryX) {
817
+ this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
818
+ this.indicatorStyle.width = this.width + 'px';
819
+ x = this.maxPosX + this.indicatorWidth - this.width;
820
+ } else if (this.width != this.indicatorWidth) {
821
+ this.width = this.indicatorWidth;
822
+ this.indicatorStyle.width = this.width + 'px';
823
+ }
824
+
825
+ if (y < this.minBoundaryY) {
826
+ this.height = Math.max(this.indicatorHeight + y * 3, 8);
827
+ this.indicatorStyle.height = this.height + 'px';
828
+ y = this.minBoundaryY;
829
+ } else if (y > this.maxBoundaryY) {
830
+ this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
831
+ this.indicatorStyle.height = this.height + 'px';
832
+ y = this.maxPosY + this.indicatorHeight - this.height;
833
+ } else if (this.height != this.indicatorHeight) {
834
+ this.height = this.indicatorHeight;
835
+ this.indicatorStyle.height = this.height + 'px';
836
+ }
837
+
838
+ this.x = x;
839
+ this.y = y;
840
+
841
+ this.indicatorStyle['webkitTransform'] = this.scroller._getTranslateStr(x, y);
842
+
843
+ },
844
+ fade: function(val, hold) {
845
+ if (hold && !this.visible) {
846
+ return;
847
+ }
848
+
849
+ clearTimeout(this.fadeTimeout);
850
+ this.fadeTimeout = null;
851
+
852
+ var time = val ? 250 : 500,
853
+ delay = val ? 0 : 300;
854
+
855
+ val = val ? '1' : '0';
856
+
857
+ this.wrapperStyle['webkitTransitionDuration'] = time + 'ms';
858
+
859
+ this.fadeTimeout = setTimeout((function(val) {
860
+ this.wrapperStyle.opacity = val;
861
+ this.visible = +val;
862
+ }).bind(this, val), delay);
863
+ }
864
+ };
865
+
866
+ $.Scroll = Scroll;
867
+
868
+ $.fn.scroll = function(options) {
869
+ var scrollApis = [];
870
+ this.each(function() {
871
+ var scrollApi = null;
872
+ var self = this;
873
+ var id = self.getAttribute('data-scroll');
874
+ if (!id) {
875
+ id = ++$.uuid;
876
+ var _options = $.extend({}, options);
877
+ if (self.classList.contains($.className('segmented-control'))) {
878
+ _options = $.extend(_options, {
879
+ scrollY: false,
880
+ scrollX: true,
881
+ indicators: false,
882
+ snap: $.classSelector('.control-item')
883
+ });
884
+ }
885
+ $.data[id] = scrollApi = new Scroll(self, _options);
886
+ self.setAttribute('data-scroll', id);
887
+ } else {
888
+ scrollApi = $.data[id];
889
+ }
890
+ scrollApis.push(scrollApi);
891
+ });
892
+ return scrollApis.length === 1 ? scrollApis[0] : scrollApis;
893
+ };
894
+ })(mui, window, document);