iugu-ux 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/lib/iugu-ux/version.rb +1 -1
  2. data/sandbox/app/assets/javascripts/web-app/config.js.erb +2 -0
  3. data/sandbox/app/assets/javascripts/web-app/usecode/root-view.coffee +2 -8
  4. data/sandbox/app/assets/javascripts/web-app/usecode/router.coffee +2 -2
  5. data/sandbox/log/development.log +43259 -0
  6. data/sandbox/tmp/cache/assets/C12/7B0/sprockets%2F22b589210b25163d0632276189db33a7 +0 -0
  7. data/sandbox/tmp/cache/assets/C48/D00/sprockets%2F4a51b39094a347e3e325005c7847551c +0 -0
  8. data/sandbox/tmp/cache/assets/C49/3B0/sprockets%2F405c7112191eed23e8b860254281e763 +0 -0
  9. data/sandbox/tmp/cache/assets/C4F/3A0/sprockets%2F41918e8d7b402652a5649e4b7134d620 +0 -0
  10. data/sandbox/tmp/cache/assets/C55/1B0/sprockets%2F413864885359794c0b415c5c012fd8b4 +0 -0
  11. data/sandbox/tmp/cache/assets/C59/510/sprockets%2Fb85817b45126c2167b27e636305a98e9 +0 -0
  12. data/sandbox/tmp/cache/assets/C5E/340/sprockets%2Fcaec1317015c08109f31f190314243b2 +0 -0
  13. data/sandbox/tmp/cache/assets/C60/360/sprockets%2Fb7a62e5a9315f80120493f865587d982 +0 -0
  14. data/sandbox/tmp/cache/assets/C70/570/sprockets%2F0bba1d02704630161a045f6d69178f67 +0 -0
  15. data/sandbox/tmp/cache/assets/C7A/F30/sprockets%2F70249181577b261a3ea8851b530f1e7c +0 -0
  16. data/sandbox/tmp/cache/assets/C84/8A0/sprockets%2F657cb456925d084af0c068e7268410e4 +0 -0
  17. data/sandbox/tmp/cache/assets/CA2/760/sprockets%2Fb298c140b2372622351f1ef6b0815f3e +0 -0
  18. data/sandbox/tmp/cache/assets/CA7/BA0/sprockets%2F13bef11836047bf35479da52332ef333 +0 -0
  19. data/sandbox/tmp/cache/assets/CA9/4B0/sprockets%2F8214f97a129c43264cfbf5038a00f445 +0 -0
  20. data/sandbox/tmp/cache/assets/CAA/A60/sprockets%2F24be3f03266d267f7f744cbf25145042 +0 -0
  21. data/sandbox/tmp/cache/assets/CB3/580/sprockets%2F617f5c4036f089509f6bb627eb264c13 +0 -0
  22. data/sandbox/tmp/cache/assets/CB7/810/sprockets%2F2668b0d95254a1c8665ee5c2116e993b +0 -0
  23. data/sandbox/tmp/cache/assets/CB8/CD0/sprockets%2Feb118c352d4b698783e25be37085f344 +0 -0
  24. data/sandbox/tmp/cache/assets/CB9/9D0/sprockets%2F893272529e62fea11982e442c0df4c49 +0 -0
  25. data/sandbox/tmp/cache/assets/CBD/660/sprockets%2Ff5804153e42afac525289f4864716fd8 +0 -0
  26. data/sandbox/tmp/cache/assets/CC7/EB0/sprockets%2F079d3b368c9e843b78c90079f26d628b +0 -0
  27. data/sandbox/tmp/cache/assets/CC8/510/sprockets%2F868a1670f8822e6b7847dd22e747a66f +0 -0
  28. data/sandbox/tmp/cache/assets/CCA/850/sprockets%2F1d05d32f046ec7313b0d3619a232d73f +0 -0
  29. data/sandbox/tmp/cache/assets/CCB/400/sprockets%2F1530d5680131ba31d7175dcb56e235ce +0 -0
  30. data/sandbox/tmp/cache/assets/CCC/CE0/sprockets%2F58c83aa4c29a223e9001079ec505b20d +0 -0
  31. data/sandbox/tmp/cache/assets/CD7/0E0/sprockets%2Fb7291915fd78d50026c443b2c63fa6b0 +0 -0
  32. data/sandbox/tmp/cache/assets/CDB/8F0/sprockets%2Fab75481b4dc342c6802664b5ef1f6371 +0 -0
  33. data/sandbox/tmp/cache/assets/CDB/DC0/sprockets%2F2544a1d0571986bce7ea0bea29732709 +0 -0
  34. data/sandbox/tmp/cache/assets/CDB/E30/sprockets%2F918458a88fec2cd01991c003b2318ab7 +0 -0
  35. data/sandbox/tmp/cache/assets/CDD/540/sprockets%2F63653bdd74a1c57059f14a1758a6a53e +0 -0
  36. data/sandbox/tmp/cache/assets/CDE/5C0/sprockets%2F794c70924436be60f2ec52426aa8cd61 +0 -0
  37. data/sandbox/tmp/cache/assets/CDE/B50/sprockets%2F385b6715594d06e9071224bafb8b2ac8 +0 -0
  38. data/sandbox/tmp/cache/assets/CE3/270/sprockets%2F545647acc617e0f78f4cb771b8a24460 +0 -0
  39. data/sandbox/tmp/cache/assets/CED/340/sprockets%2F2f33f5d63e037a9f9b859f6c25139e30 +0 -0
  40. data/sandbox/tmp/cache/assets/CFA/EE0/sprockets%2Fd95b64bc8b83485c8f3960c625885dc6 +0 -0
  41. data/sandbox/tmp/cache/assets/CFD/6C0/sprockets%2F1203d4bbdfe1aac02f896e2447006951 +0 -0
  42. data/sandbox/tmp/cache/assets/D02/BA0/sprockets%2F3479fc60a2e746bc3244cc41127e4eb0 +0 -0
  43. data/sandbox/tmp/cache/assets/D06/350/sprockets%2F930f6313451d773a6f0daae4b5485ca4 +0 -0
  44. data/sandbox/tmp/cache/assets/D08/ED0/sprockets%2Fcb1aee736d3b287a872298b7741b012b +0 -0
  45. data/sandbox/tmp/cache/assets/D09/DB0/sprockets%2F21a7ee2fd49111e1378c6f7118fd230e +0 -0
  46. data/sandbox/tmp/cache/assets/D10/260/sprockets%2F34be45a2946b38f2577ee0d334d5a63d +0 -0
  47. data/sandbox/tmp/cache/assets/D14/AF0/sprockets%2F24fd44697221a182e489cc7dddb571e2 +0 -0
  48. data/sandbox/tmp/cache/assets/D15/450/sprockets%2Fe059ee5f777123d281b0a963b292afe7 +0 -0
  49. data/sandbox/tmp/cache/assets/D1A/B70/sprockets%2F47ae92dd9d034b32098b19bf8f2475a9 +0 -0
  50. data/sandbox/tmp/cache/assets/D1D/310/sprockets%2Fa6650b89ce8152c1cd762d6df44546f9 +0 -0
  51. data/sandbox/tmp/cache/assets/D26/0C0/sprockets%2F44ba33f7338d8b57eb37f98e8c861e08 +0 -0
  52. data/sandbox/tmp/cache/assets/D2E/E00/sprockets%2Fa22b402f5d65fd3ac148bef371b39061 +0 -0
  53. data/sandbox/tmp/cache/assets/D32/840/sprockets%2Fdfe84878329efef68a1782d749083d6b +0 -0
  54. data/sandbox/tmp/cache/assets/D34/280/sprockets%2F0fcf69c7e8fd9961e1158d70583e8f95 +0 -0
  55. data/sandbox/tmp/cache/assets/D34/3E0/sprockets%2F46a73c17c9a561115944df004dbbdd7b +0 -0
  56. data/sandbox/tmp/cache/assets/D35/AC0/sprockets%2F67d23b05f2a7bc455d0f5f408ca6d523 +0 -0
  57. data/sandbox/tmp/cache/assets/D37/1E0/sprockets%2Fc42800bd200fbf8edbdf9410949590a4 +0 -0
  58. data/sandbox/tmp/cache/assets/D39/880/sprockets%2F30ace94e10312e02fdf5d4a398393f8b +0 -0
  59. data/sandbox/tmp/cache/assets/D3C/840/sprockets%2F49effd15c5894a93202ad06b57aab085 +0 -0
  60. data/sandbox/tmp/cache/assets/D3D/B80/sprockets%2F75df7c9d480cfbe1f976999e7647d771 +0 -0
  61. data/sandbox/tmp/cache/assets/D40/8A0/sprockets%2F4483a17992b57cddb5dee15e327d30e3 +0 -0
  62. data/sandbox/tmp/cache/assets/D46/650/sprockets%2Fba1459a80d8874a816f88ffec22019ac +0 -0
  63. data/sandbox/tmp/cache/assets/D49/490/sprockets%2F0fa1c0108b93ed47893971f6b9da7ef4 +0 -0
  64. data/sandbox/tmp/cache/assets/D4A/1A0/sprockets%2Fb746360a8b3ce79c57e74a9c15309fdd +0 -0
  65. data/sandbox/tmp/cache/assets/D4C/8E0/sprockets%2F598b784236bf0a9baea474b6b9e1377f +0 -0
  66. data/sandbox/tmp/cache/assets/D4D/5C0/sprockets%2F66eaa47a7875ec8a24a5dbe465e75753 +0 -0
  67. data/sandbox/tmp/cache/assets/D4E/580/sprockets%2Fc44f860c313495c861c6e85f7dadd5b9 +0 -0
  68. data/sandbox/tmp/cache/assets/D52/870/sprockets%2Ffa371b6ca7e8969ae9d665288aa3d274 +0 -0
  69. data/sandbox/tmp/cache/assets/D55/310/sprockets%2F2b9be79ca64ec7d294d4825e21696ce9 +0 -0
  70. data/sandbox/tmp/cache/assets/D5C/200/sprockets%2Fcd323e6f7545cee0b3ba1e84d7520b00 +0 -0
  71. data/sandbox/tmp/cache/assets/D5E/290/sprockets%2F22fb620af04e31f058ba64ec4386bb8a +0 -0
  72. data/sandbox/tmp/cache/assets/D62/690/sprockets%2F11532c31a6be258097db31bbeb9ff35d +0 -0
  73. data/sandbox/tmp/cache/assets/D68/460/sprockets%2Fea4f165c56f90dc5b03663eec414f3c1 +0 -0
  74. data/sandbox/tmp/cache/assets/D6B/0F0/sprockets%2F3609df3f470bd24af26a51de476cef05 +0 -0
  75. data/sandbox/tmp/cache/assets/D6B/790/sprockets%2Fba3068e1e3b47233f6febb3307dc5d97 +0 -0
  76. data/sandbox/tmp/cache/assets/D6E/AE0/sprockets%2Fe193ea7b03f186ad2a9515fc78fa8c21 +0 -0
  77. data/sandbox/tmp/cache/assets/D70/320/sprockets%2Fb81a3eab4ea93cf21fd7585436b8a169 +0 -0
  78. data/sandbox/tmp/cache/assets/D74/0A0/sprockets%2Fc1392b79af6b88250b634479cbf2bcfc +0 -0
  79. data/sandbox/tmp/cache/assets/D76/FE0/sprockets%2F55218c9e551f686465ae4fdcba0e0b9f +0 -0
  80. data/sandbox/tmp/cache/assets/D7A/2D0/sprockets%2F1e48dabd17757b995da1d953cf1fd770 +0 -0
  81. data/sandbox/tmp/cache/assets/D7A/D40/sprockets%2F4d2bc08f2787a3870ff93e0e0f7bc67e +0 -0
  82. data/sandbox/tmp/cache/assets/D7D/2C0/sprockets%2Fdc76b19d5f8ce4e6e4e9c735c223091f +0 -0
  83. data/sandbox/tmp/cache/assets/D88/B70/sprockets%2F9b378be843af782b809c5ce3d6f6d47f +0 -0
  84. data/sandbox/tmp/cache/assets/D89/670/sprockets%2Fbf838afe9adf908d9ec59bc552833285 +0 -0
  85. data/sandbox/tmp/cache/assets/D8C/D40/sprockets%2Fc4a00154a0e1c15a495ce4d49c9f0ccf +0 -0
  86. data/sandbox/tmp/cache/assets/D8D/EE0/sprockets%2F1206b4a24b16b0f7dfaea382ced088c6 +0 -0
  87. data/sandbox/tmp/cache/assets/D8F/0D0/sprockets%2Facc7af71e18e4a53a0019c2bb73d918b +0 -0
  88. data/sandbox/tmp/cache/assets/D96/940/sprockets%2F6a2c3af22b173eb975f382b4cdcd8c41 +0 -0
  89. data/sandbox/tmp/cache/assets/D96/E90/sprockets%2F0d5f451deca7e6811663f30afc3a4fd4 +0 -0
  90. data/sandbox/tmp/cache/assets/D97/180/sprockets%2F933323d1c368cfeda7a0cacdbd295933 +0 -0
  91. data/sandbox/tmp/cache/assets/D9F/C80/sprockets%2Ffa9d12280c37c395d5b1d9ed2e1e3e9a +0 -0
  92. data/sandbox/tmp/cache/assets/DA5/EA0/sprockets%2Fc2e6b41187b059dbddd8dbd7cb884482 +0 -0
  93. data/sandbox/tmp/cache/assets/DAA/3A0/sprockets%2Fe27f2e6b2be916baf8e334d4f6a967c4 +0 -0
  94. data/sandbox/tmp/cache/assets/DAD/190/sprockets%2Fbee62a5d7a8cd35a33763f1cd879de59 +0 -0
  95. data/sandbox/tmp/cache/assets/DB5/EC0/sprockets%2Fde17edd0f2eca28280c1a27ac5c510c3 +0 -0
  96. data/sandbox/tmp/cache/assets/DBE/5E0/sprockets%2F7663abb4baaadfc7e6a48f1150f32b62 +0 -0
  97. data/sandbox/tmp/cache/assets/DBF/840/sprockets%2Fd4e283da1ca8144fab20ff164e7cba28 +0 -0
  98. data/sandbox/tmp/cache/assets/DC3/F40/sprockets%2Fe0bf54d65f601a29af05bd5fbe06a2f6 +0 -0
  99. data/sandbox/tmp/cache/assets/DCA/FD0/sprockets%2F0b59a77adfc61bb863e708ba262ce6bd +0 -0
  100. data/sandbox/tmp/cache/assets/DCB/100/sprockets%2Fd313bd7561b538fb7f2c4ab89dba5b7b +0 -0
  101. data/sandbox/tmp/cache/assets/DCB/200/sprockets%2Fe556cbde6fb38c98aa347cbf11ec3331 +0 -0
  102. data/sandbox/tmp/cache/assets/DD5/040/sprockets%2F8b8bc1dd8d844edda81c52b7bd29a926 +0 -0
  103. data/sandbox/tmp/cache/assets/DD7/9B0/sprockets%2F9f2c0826bd7ae7b745ae8da6db48c26e +0 -0
  104. data/sandbox/tmp/cache/assets/DD8/3B0/sprockets%2Fef4ddeef4487be0bf8c6412714f61e8a +0 -0
  105. data/sandbox/tmp/cache/assets/DE5/390/sprockets%2F24a1cda6893cebd53997dc859def67cd +0 -0
  106. data/sandbox/tmp/cache/assets/DF0/D20/sprockets%2F3a22be815414fea0fac78cfa50d09faf +0 -0
  107. data/sandbox/tmp/cache/assets/DF6/B10/sprockets%2F5ed8ba35afbb3f0c89f1b1732ecf13d5 +0 -0
  108. data/sandbox/tmp/cache/assets/DFC/F70/sprockets%2F21c3daa07778fe7edba83edf5f3313cd +0 -0
  109. data/sandbox/tmp/cache/assets/E05/2E0/sprockets%2F92ecbfa92baf6e394ce6c39d731b7cd2 +0 -0
  110. data/sandbox/tmp/cache/assets/E10/410/sprockets%2Ffca98bf9e72b4ee6b36c5a8d88c226be +0 -0
  111. data/sandbox/tmp/cache/assets/E12/7A0/sprockets%2F91cef5f7cb58b6d4dfddd803ff6a9571 +0 -0
  112. data/sandbox/tmp/cache/assets/E2D/4F0/sprockets%2F93febe26a8de2344ec8d1fbe1525afdb +0 -0
  113. data/sandbox/tmp/cache/assets/E3F/FE0/sprockets%2Fbbbb6f82edbdac31a0c71ce0b04718ac +0 -0
  114. data/sandbox/tmp/cache/assets/E43/730/sprockets%2Fd4d2a9de1ff9af8f488ce4b4d9e307cf +0 -0
  115. data/sandbox/tmp/cache/sass/8e0849d701bca2f5a178ed1215813b1316068a4d/components.sassc +0 -0
  116. data/vendor/assets/javascripts/iugu-ux/capabilities.js +4 -2
  117. data/vendor/assets/javascripts/iugu-ux/components/usecode/iugu-ui-base.js.coffee +25 -0
  118. data/vendor/assets/javascripts/iugu-ux/web-app.js +2 -0
  119. data/vendor/assets/javascripts/vendor.js +1 -0
  120. data/vendor/assets/javascripts/vendor/iscroll.js +1105 -1080
  121. data/vendor/assets/stylesheets/iugu-ux/components.sass +10 -2
  122. metadata +94 -30
@@ -1,10 +1,10 @@
1
1
  var BrowserDetect = {
2
2
  init: function () {
3
- this.browser = this.searchString(this.dataBrowser) || "unknow";
3
+ this.browser = this.searchString(this.dataBrowser) || "unknown";
4
4
  this.version = this.searchVersion(navigator.userAgent)
5
5
  || this.searchVersion(navigator.appVersion)
6
6
  || "unknown_version";
7
- this.OS = this.searchString(this.dataOS) || "unknow_os";
7
+ this.OS = this.searchString(this.dataOS) || "unknown_os";
8
8
  },
9
9
  searchString: function (data) {
10
10
  for (var i=0;i<data.length;i++) {
@@ -132,6 +132,7 @@ $( function() {
132
132
  window.IS_DESKTOP = false;
133
133
  window.IS_IOS = false;
134
134
  window.IS_ANDROID = false;
135
+ window.IS_DEPRECATED_ANDROID = false;
135
136
 
136
137
  $("html").removeClass("no-js").addClass("js");
137
138
  $("html").removeClass("not-ready").addClass("ready");
@@ -150,6 +151,7 @@ $( function() {
150
151
  if (androidversion < 3)
151
152
  {
152
153
  $("html").addClass( 'deprecated_android' );
154
+ window.IS_DEPRECATED_ANDROID = true;
153
155
  }
154
156
  }
155
157
 
@@ -18,17 +18,42 @@ class IuguUI.Base extends Backbone.View
18
18
 
19
19
  @
20
20
 
21
+ handleDeprecated: ->
22
+ if window.app._iscroll_instances == undefined
23
+ window.app._iscroll_instances = []
24
+
25
+ unless window.IS_DEPRECATED_ANDROID
26
+ return
27
+
28
+ @$(".handle-scrolling").each( (index,handle_scrolling_elm) ->
29
+ elm = handle_scrolling_elm.parentNode
30
+ if $(handle_scrolling_elm).attr("initialized") != true
31
+ $(handle_scrolling_elm).css('overflow-y','visible')
32
+ $(handle_scrolling_elm).css('height','auto')
33
+ $(handle_scrolling_elm).attr("initialized",true)
34
+ window.app._iscroll_instances.push( new iScroll( elm, { hideScrollbar: false, hScroll: false } ) )
35
+ )
36
+
21
37
  render: ->
22
38
  $(@el).html @getLayout() @context()
23
39
 
24
40
  if @className
25
41
  $(@el).addClass @className
26
42
 
43
+ @handleDeprecated()
44
+
45
+ if window.app._iscroll_instances
46
+ for iscroll in window.app._iscroll_instances
47
+ if iscroll.wrapper
48
+ iscroll.refresh()
49
+
27
50
  @
28
51
 
29
52
  renderPartial: ( layout, target, context=@context ) ->
30
53
  $(target).html @getLayout(target) context
31
54
 
55
+ @handleDeprecated()
56
+
32
57
  getLayout: (layout_file=@layout) ->
33
58
  if JST[ "web-app/presenters/" + layout_file ]
34
59
  return JST[ "web-app/presenters/" + layout_file ]
@@ -12,6 +12,7 @@
12
12
  // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
13
13
  // GO AFTER THE REQUIRES BELOW.
14
14
  //
15
+ //= require_self
15
16
  //= require web-app/environment
16
17
  //= require web-app/config
17
18
  //= require web-app/comm
@@ -29,3 +30,4 @@
29
30
  //= require web-app/models
30
31
  //= require web-app/presenters
31
32
  //= require web-app/usecode
33
+ IuguUI = {}
@@ -28,3 +28,4 @@
28
28
  //= require ./vendor/rivets.js
29
29
  //= require ./vendor/async.js
30
30
  //= require ./vendor/tasks.js
31
+ //= require ./vendor/iscroll.js
@@ -1,1080 +1,1105 @@
1
- /*!
2
- * iScroll v4.1.9 ~ Copyright (c) 2011 Matteo Spinelli, http://cubiq.org
3
- * Released under MIT license, http://cubiq.org/license
4
- */
5
- (function(){
6
- var m = Math,
7
- mround = function (r) { return r >> 0; },
8
- vendor = (/webkit/i).test(navigator.appVersion) ? 'webkit' :
9
- (/firefox/i).test(navigator.userAgent) ? 'Moz' :
10
- (/trident/i).test(navigator.userAgent) ? 'ms' :
11
- 'opera' in window ? 'O' : '',
12
-
13
- // Browser capabilities44
14
- isAndroid = (/android/gi).test(navigator.appVersion),
15
- isIDevice = (/iphone|ipad/gi).test(navigator.appVersion),
16
- isPlaybook = (/playbook/gi).test(navigator.appVersion),
17
- isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),
18
-
19
- has3d = 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix(),
20
- hasTouch = 'ontouchstart' in window && !isTouchPad,
21
- hasTransform = vendor + 'Transform' in document.documentElement.style,
22
- hasTransitionEnd = isIDevice || isPlaybook,
23
-
24
- nextFrame = (function() {
25
- return window.requestAnimationFrame
26
- || window.webkitRequestAnimationFrame
27
- || window.mozRequestAnimationFrame
28
- || window.oRequestAnimationFrame
29
- || window.msRequestAnimationFrame
30
- || function(callback) { return setTimeout(callback, 1); }
31
- })(),
32
- cancelFrame = (function () {
33
- return window.cancelRequestAnimationFrame
34
- || window.webkitCancelAnimationFrame
35
- || window.webkitCancelRequestAnimationFrame
36
- || window.mozCancelRequestAnimationFrame
37
- || window.oCancelRequestAnimationFrame
38
- || window.msCancelRequestAnimationFrame
39
- || clearTimeout
40
- })(),
41
-
42
- // Events
43
- RESIZE_EV = 'onorientationchange' in window ? 'orientationchange' : 'resize',
44
- START_EV = hasTouch ? 'touchstart' : 'mousedown',
45
- MOVE_EV = hasTouch ? 'touchmove' : 'mousemove',
46
- END_EV = hasTouch ? 'touchend' : 'mouseup',
47
- CANCEL_EV = hasTouch ? 'touchcancel' : 'mouseup',
48
- WHEEL_EV = vendor == 'Moz' ? 'DOMMouseScroll' : 'mousewheel',
49
-
50
- // Helpers
51
- trnOpen = 'translate' + (has3d ? '3d(' : '('),
52
- trnClose = has3d ? ',0)' : ')',
53
-
54
- // Constructor
55
- iScroll = function (el, options) {
56
- var that = this,
57
- doc = document,
58
- i;
59
-
60
- that.wrapper = typeof el == 'object' ? el : doc.getElementById(el);
61
- that.wrapper.style.overflow = 'hidden';
62
- that.scroller = that.wrapper.children[0];
63
-
64
- // Default options
65
- that.options = {
66
- hScroll: true,
67
- vScroll: true,
68
- x: 0,
69
- y: 0,
70
- bounce: true,
71
- bounceLock: false,
72
- momentum: true,
73
- lockDirection: true,
74
- useTransform: true,
75
- useTransition: false,
76
- topOffset: 0,
77
- checkDOMChanges: false, // Experimental
78
-
79
- // Scrollbar
80
- hScrollbar: true,
81
- vScrollbar: true,
82
- fixedScrollbar: isAndroid,
83
- hideScrollbar: isIDevice,
84
- fadeScrollbar: isIDevice && has3d,
85
- scrollbarClass: '',
86
-
87
- // Zoom
88
- zoom: false,
89
- zoomMin: 1,
90
- zoomMax: 4,
91
- doubleTapZoom: 2,
92
- wheelAction: 'scroll',
93
-
94
- // Snap
95
- snap: false,
96
- snapThreshold: 1,
97
-
98
- // Events
99
- onRefresh: null,
100
- onBeforeScrollStart: function (e) { e.preventDefault(); },
101
- onScrollStart: null,
102
- onBeforeScrollMove: null,
103
- onScrollMove: null,
104
- onBeforeScrollEnd: null,
105
- onScrollEnd: null,
106
- onTouchEnd: null,
107
- onDestroy: null,
108
- onZoomStart: null,
109
- onZoom: null,
110
- onZoomEnd: null
111
- };
112
-
113
- // User defined options
114
- for (i in options) that.options[i] = options[i];
115
-
116
- // Set starting position
117
- that.x = that.options.x;
118
- that.y = that.options.y;
119
-
120
- // Normalize options
121
- that.options.useTransform = hasTransform ? that.options.useTransform : false;
122
- that.options.hScrollbar = that.options.hScroll && that.options.hScrollbar;
123
- that.options.vScrollbar = that.options.vScroll && that.options.vScrollbar;
124
- that.options.zoom = that.options.useTransform && that.options.zoom;
125
- that.options.useTransition = hasTransitionEnd && that.options.useTransition;
126
-
127
- // Helpers FIX ANDROID BUG!
128
- // translate3d and scale doesn't work together!
129
- // Ignoring 3d ONLY WHEN YOU SET that.options.zoom
130
- if ( that.options.zoom && isAndroid ){
131
- trnOpen = 'translate(';
132
- trnClose = ')';
133
- }
134
-
135
- // Set some default styles
136
- that.scroller.style[vendor + 'TransitionProperty'] = that.options.useTransform ? '-' + vendor.toLowerCase() + '-transform' : 'top left';
137
- that.scroller.style[vendor + 'TransitionDuration'] = '0';
138
- that.scroller.style[vendor + 'TransformOrigin'] = '0 0';
139
- if (that.options.useTransition) that.scroller.style[vendor + 'TransitionTimingFunction'] = 'cubic-bezier(0.33,0.66,0.66,1)';
140
-
141
- if (that.options.useTransform) that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose;
142
- else that.scroller.style.cssText += ';position:absolute;top:' + that.y + 'px;left:' + that.x + 'px';
143
-
144
- if (that.options.useTransition) that.options.fixedScrollbar = true;
145
-
146
- that.refresh();
147
-
148
- that._bind(RESIZE_EV, window);
149
- that._bind(START_EV);
150
- if (!hasTouch) {
151
- that._bind('mouseout', that.wrapper);
152
- if (that.options.wheelAction != 'none')
153
- that._bind(WHEEL_EV);
154
- }
155
-
156
- if (that.options.checkDOMChanges) that.checkDOMTime = setInterval(function () {
157
- that._checkDOMChanges();
158
- }, 500);
159
- };
160
-
161
- // Prototype
162
- iScroll.prototype = {
163
- enabled: true,
164
- x: 0,
165
- y: 0,
166
- steps: [],
167
- scale: 1,
168
- currPageX: 0, currPageY: 0,
169
- pagesX: [], pagesY: [],
170
- aniTime: null,
171
- wheelZoomCount: 0,
172
-
173
- handleEvent: function (e) {
174
- var that = this;
175
- switch(e.type) {
176
- case START_EV:
177
- if (!hasTouch && e.button !== 0) return;
178
- that._start(e);
179
- break;
180
- case MOVE_EV: that._move(e); break;
181
- case END_EV:
182
- case CANCEL_EV: that._end(e); break;
183
- case RESIZE_EV: that._resize(); break;
184
- case WHEEL_EV: that._wheel(e); break;
185
- case 'mouseout': that._mouseout(e); break;
186
- case 'webkitTransitionEnd': that._transitionEnd(e); break;
187
- }
188
- },
189
-
190
- _checkDOMChanges: function () {
191
- if (this.moved || this.zoomed || this.animating ||
192
- (this.scrollerW == this.scroller.offsetWidth * this.scale && this.scrollerH == this.scroller.offsetHeight * this.scale)) return;
193
-
194
- this.refresh();
195
- },
196
-
197
- _scrollbar: function (dir) {
198
- var that = this,
199
- doc = document,
200
- bar;
201
-
202
- if (!that[dir + 'Scrollbar']) {
203
- if (that[dir + 'ScrollbarWrapper']) {
204
- if (hasTransform) that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = '';
205
- that[dir + 'ScrollbarWrapper'].parentNode.removeChild(that[dir + 'ScrollbarWrapper']);
206
- that[dir + 'ScrollbarWrapper'] = null;
207
- that[dir + 'ScrollbarIndicator'] = null;
208
- }
209
-
210
- return;
211
- }
212
-
213
- if (!that[dir + 'ScrollbarWrapper']) {
214
- // Create the scrollbar wrapper
215
- bar = doc.createElement('div');
216
-
217
- if (that.options.scrollbarClass) bar.className = that.options.scrollbarClass + dir.toUpperCase();
218
- else bar.style.cssText = 'position:absolute;z-index:100;' + (dir == 'h' ? 'height:7px;bottom:1px;left:2px;right:' + (that.vScrollbar ? '7' : '2') + 'px' : 'width:7px;bottom:' + (that.hScrollbar ? '7' : '2') + 'px;top:2px;right:1px');
219
-
220
- bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:opacity;-' + vendor + '-transition-duration:' + (that.options.fadeScrollbar ? '350ms' : '0') + ';overflow:hidden;opacity:' + (that.options.hideScrollbar ? '0' : '1');
221
-
222
- that.wrapper.appendChild(bar);
223
- that[dir + 'ScrollbarWrapper'] = bar;
224
-
225
- // Create the scrollbar indicator
226
- bar = doc.createElement('div');
227
- if (!that.options.scrollbarClass) {
228
- bar.style.cssText = 'position:absolute;z-index:100;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);-' + vendor + '-background-clip:padding-box;-' + vendor + '-box-sizing:border-box;' + (dir == 'h' ? 'height:100%' : 'width:100%') + ';-' + vendor + '-border-radius:3px;border-radius:3px';
229
- }
230
- bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:-' + vendor + '-transform;-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);-' + vendor + '-transition-duration:0;-' + vendor + '-transform:' + trnOpen + '0,0' + trnClose;
231
- if (that.options.useTransition) bar.style.cssText += ';-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1)';
232
-
233
- that[dir + 'ScrollbarWrapper'].appendChild(bar);
234
- that[dir + 'ScrollbarIndicator'] = bar;
235
- }
236
-
237
- if (dir == 'h') {
238
- that.hScrollbarSize = that.hScrollbarWrapper.clientWidth;
239
- that.hScrollbarIndicatorSize = m.max(mround(that.hScrollbarSize * that.hScrollbarSize / that.scrollerW), 8);
240
- that.hScrollbarIndicator.style.width = that.hScrollbarIndicatorSize + 'px';
241
- that.hScrollbarMaxScroll = that.hScrollbarSize - that.hScrollbarIndicatorSize;
242
- that.hScrollbarProp = that.hScrollbarMaxScroll / that.maxScrollX;
243
- } else {
244
- that.vScrollbarSize = that.vScrollbarWrapper.clientHeight;
245
- that.vScrollbarIndicatorSize = m.max(mround(that.vScrollbarSize * that.vScrollbarSize / that.scrollerH), 8);
246
- that.vScrollbarIndicator.style.height = that.vScrollbarIndicatorSize + 'px';
247
- that.vScrollbarMaxScroll = that.vScrollbarSize - that.vScrollbarIndicatorSize;
248
- that.vScrollbarProp = that.vScrollbarMaxScroll / that.maxScrollY;
249
- }
250
-
251
- // Reset position
252
- that._scrollbarPos(dir, true);
253
- },
254
-
255
- _resize: function () {
256
- var that = this;
257
- setTimeout(function () { that.refresh(); }, isAndroid ? 200 : 0);
258
- },
259
-
260
- _pos: function (x, y) {
261
- x = this.hScroll ? x : 0;
262
- y = this.vScroll ? y : 0;
263
-
264
- if (this.options.useTransform) {
265
- this.scroller.style[vendor + 'Transform'] = trnOpen + x + 'px,' + y + 'px' + trnClose + ' scale(' + this.scale + ')';
266
- } else {
267
- x = mround(x);
268
- y = mround(y);
269
- this.scroller.style.left = x + 'px';
270
- this.scroller.style.top = y + 'px';
271
- }
272
-
273
- this.x = x;
274
- this.y = y;
275
-
276
- this._scrollbarPos('h');
277
- this._scrollbarPos('v');
278
- },
279
-
280
- _scrollbarPos: function (dir, hidden) {
281
- var that = this,
282
- pos = dir == 'h' ? that.x : that.y,
283
- size;
284
-
285
- if (!that[dir + 'Scrollbar']) return;
286
-
287
- pos = that[dir + 'ScrollbarProp'] * pos;
288
-
289
- if (pos < 0) {
290
- if (!that.options.fixedScrollbar) {
291
- size = that[dir + 'ScrollbarIndicatorSize'] + mround(pos * 3);
292
- if (size < 8) size = 8;
293
- that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';
294
- }
295
- pos = 0;
296
- } else if (pos > that[dir + 'ScrollbarMaxScroll']) {
297
- if (!that.options.fixedScrollbar) {
298
- size = that[dir + 'ScrollbarIndicatorSize'] - mround((pos - that[dir + 'ScrollbarMaxScroll']) * 3);
299
- if (size < 8) size = 8;
300
- that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';
301
- pos = that[dir + 'ScrollbarMaxScroll'] + (that[dir + 'ScrollbarIndicatorSize'] - size);
302
- } else {
303
- pos = that[dir + 'ScrollbarMaxScroll'];
304
- }
305
- }
306
-
307
- that[dir + 'ScrollbarWrapper'].style[vendor + 'TransitionDelay'] = '0';
308
- that[dir + 'ScrollbarWrapper'].style.opacity = hidden && that.options.hideScrollbar ? '0' : '1';
309
- that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = trnOpen + (dir == 'h' ? pos + 'px,0' : '0,' + pos + 'px') + trnClose;
310
- },
311
-
312
- _start: function (e) {
313
- var that = this,
314
- point = hasTouch ? e.touches[0] : e,
315
- matrix, x, y,
316
- c1, c2;
317
-
318
- if (!that.enabled) return;
319
-
320
- if (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);
321
-
322
- if (that.options.useTransition || that.options.zoom) that._transitionTime(0);
323
-
324
- that.moved = false;
325
- that.animating = false;
326
- that.zoomed = false;
327
- that.distX = 0;
328
- that.distY = 0;
329
- that.absDistX = 0;
330
- that.absDistY = 0;
331
- that.dirX = 0;
332
- that.dirY = 0;
333
-
334
- // Gesture start
335
- if (that.options.zoom && hasTouch && e.touches.length > 1) {
336
- c1 = m.abs(e.touches[0].pageX-e.touches[1].pageX);
337
- c2 = m.abs(e.touches[0].pageY-e.touches[1].pageY);
338
- that.touchesDistStart = m.sqrt(c1 * c1 + c2 * c2);
339
-
340
- that.originX = m.abs(e.touches[0].pageX + e.touches[1].pageX - that.wrapperOffsetLeft * 2) / 2 - that.x;
341
- that.originY = m.abs(e.touches[0].pageY + e.touches[1].pageY - that.wrapperOffsetTop * 2) / 2 - that.y;
342
-
343
- if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);
344
- }
345
-
346
- if (that.options.momentum) {
347
- if (that.options.useTransform) {
348
- // Very lame general purpose alternative to CSSMatrix
349
- matrix = getComputedStyle(that.scroller, null)[vendor + 'Transform'].replace(/[^0-9-.,]/g, '').split(',');
350
- x = matrix[4] * 1;
351
- y = matrix[5] * 1;
352
- } else {
353
- x = getComputedStyle(that.scroller, null).left.replace(/[^0-9-]/g, '') * 1;
354
- y = getComputedStyle(that.scroller, null).top.replace(/[^0-9-]/g, '') * 1;
355
- }
356
-
357
- if (x != that.x || y != that.y) {
358
- if (that.options.useTransition) that._unbind('webkitTransitionEnd');
359
- else cancelFrame(that.aniTime);
360
- that.steps = [];
361
- that._pos(x, y);
362
- }
363
- }
364
-
365
- that.absStartX = that.x; // Needed by snap threshold
366
- that.absStartY = that.y;
367
-
368
- that.startX = that.x;
369
- that.startY = that.y;
370
- that.pointX = point.pageX;
371
- that.pointY = point.pageY;
372
-
373
- that.startTime = e.timeStamp || Date.now();
374
-
375
- if (that.options.onScrollStart) that.options.onScrollStart.call(that, e);
376
-
377
- that._bind(MOVE_EV);
378
- that._bind(END_EV);
379
- that._bind(CANCEL_EV);
380
- },
381
-
382
- _move: function (e) {
383
- var that = this,
384
- point = hasTouch ? e.touches[0] : e,
385
- deltaX = point.pageX - that.pointX,
386
- deltaY = point.pageY - that.pointY,
387
- newX = that.x + deltaX,
388
- newY = that.y + deltaY,
389
- c1, c2, scale,
390
- timestamp = e.timeStamp || Date.now();
391
-
392
- if (that.options.onBeforeScrollMove) that.options.onBeforeScrollMove.call(that, e);
393
-
394
- // Zoom
395
- if (that.options.zoom && hasTouch && e.touches.length > 1) {
396
- c1 = m.abs(e.touches[0].pageX - e.touches[1].pageX);
397
- c2 = m.abs(e.touches[0].pageY - e.touches[1].pageY);
398
- that.touchesDist = m.sqrt(c1*c1+c2*c2);
399
-
400
- that.zoomed = true;
401
-
402
- scale = 1 / that.touchesDistStart * that.touchesDist * this.scale;
403
-
404
- if (scale < that.options.zoomMin) scale = 0.5 * that.options.zoomMin * Math.pow(2.0, scale / that.options.zoomMin);
405
- else if (scale > that.options.zoomMax) scale = 2.0 * that.options.zoomMax * Math.pow(0.5, that.options.zoomMax / scale);
406
-
407
- that.lastScale = scale / this.scale;
408
-
409
- newX = this.originX - this.originX * that.lastScale + this.x,
410
- newY = this.originY - this.originY * that.lastScale + this.y;
411
-
412
- this.scroller.style[vendor + 'Transform'] = trnOpen + newX + 'px,' + newY + 'px' + trnClose + ' scale(' + scale + ')';
413
-
414
- if (that.options.onZoom) that.options.onZoom.call(that, e);
415
- return;
416
- }
417
-
418
- that.pointX = point.pageX;
419
- that.pointY = point.pageY;
420
-
421
- // Slow down if outside of the boundaries
422
- if (newX > 0 || newX < that.maxScrollX) {
423
- newX = that.options.bounce ? that.x + (deltaX / 2) : newX >= 0 || that.maxScrollX >= 0 ? 0 : that.maxScrollX;
424
- }
425
- if (newY > that.minScrollY || newY < that.maxScrollY) {
426
- newY = that.options.bounce ? that.y + (deltaY / 2) : newY >= that.minScrollY || that.maxScrollY >= 0 ? that.minScrollY : that.maxScrollY;
427
- }
428
-
429
- that.distX += deltaX;
430
- that.distY += deltaY;
431
- that.absDistX = m.abs(that.distX);
432
- that.absDistY = m.abs(that.distY);
433
-
434
- if (that.absDistX < 6 && that.absDistY < 6) {
435
- return;
436
- }
437
-
438
- // Lock direction
439
- if (that.options.lockDirection) {
440
- if (that.absDistX > that.absDistY + 5) {
441
- newY = that.y;
442
- deltaY = 0;
443
- } else if (that.absDistY > that.absDistX + 5) {
444
- newX = that.x;
445
- deltaX = 0;
446
- }
447
- }
448
-
449
- that.moved = true;
450
- that._pos(newX, newY);
451
- that.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
452
- that.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
453
-
454
- if (timestamp - that.startTime > 300) {
455
- that.startTime = timestamp;
456
- that.startX = that.x;
457
- that.startY = that.y;
458
- }
459
-
460
- if (that.options.onScrollMove) that.options.onScrollMove.call(that, e);
461
- },
462
-
463
- _end: function (e) {
464
- if (hasTouch && e.touches.length != 0) return;
465
-
466
- var that = this,
467
- point = hasTouch ? e.changedTouches[0] : e,
468
- target, ev,
469
- momentumX = { dist:0, time:0 },
470
- momentumY = { dist:0, time:0 },
471
- duration = (e.timeStamp || Date.now()) - that.startTime,
472
- newPosX = that.x,
473
- newPosY = that.y,
474
- distX, distY,
475
- newDuration,
476
- snap,
477
- scale;
478
-
479
- that._unbind(MOVE_EV);
480
- that._unbind(END_EV);
481
- that._unbind(CANCEL_EV);
482
-
483
- if (that.options.onBeforeScrollEnd) that.options.onBeforeScrollEnd.call(that, e);
484
-
485
- if (that.zoomed) {
486
- scale = that.scale * that.lastScale;
487
- scale = Math.max(that.options.zoomMin, scale);
488
- scale = Math.min(that.options.zoomMax, scale);
489
- that.lastScale = scale / that.scale;
490
- that.scale = scale;
491
-
492
- that.x = that.originX - that.originX * that.lastScale + that.x;
493
- that.y = that.originY - that.originY * that.lastScale + that.y;
494
-
495
- that.scroller.style[vendor + 'TransitionDuration'] = '200ms';
496
- that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose + ' scale(' + that.scale + ')';
497
-
498
- that.zoomed = false;
499
- that.refresh();
500
-
501
- if (that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);
502
- return;
503
- }
504
-
505
- if (!that.moved) {
506
- if (hasTouch) {
507
- if (that.doubleTapTimer && that.options.zoom) {
508
- // Double tapped
509
- clearTimeout(that.doubleTapTimer);
510
- that.doubleTapTimer = null;
511
- if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);
512
- that.zoom(that.pointX, that.pointY, that.scale == 1 ? that.options.doubleTapZoom : 1);
513
- if (that.options.onZoomEnd) {
514
- setTimeout(function() {
515
- that.options.onZoomEnd.call(that, e);
516
- }, 200); // 200 is default zoom duration
517
- }
518
- } else {
519
- that.doubleTapTimer = setTimeout(function () {
520
- that.doubleTapTimer = null;
521
-
522
- // Find the last touched element
523
- target = point.target;
524
- while (target.nodeType != 1) target = target.parentNode;
525
-
526
- if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
527
- ev = document.createEvent('MouseEvents');
528
- ev.initMouseEvent('click', true, true, e.view, 1,
529
- point.screenX, point.screenY, point.clientX, point.clientY,
530
- e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
531
- 0, null);
532
- ev._fake = true;
533
- target.dispatchEvent(ev);
534
- }
535
- }, that.options.zoom ? 250 : 0);
536
- }
537
- }
538
-
539
- that._resetPos(200);
540
-
541
- if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
542
- return;
543
- }
544
-
545
- if (duration < 300 && that.options.momentum) {
546
- momentumX = newPosX ? that._momentum(newPosX - that.startX, duration, -that.x, that.scrollerW - that.wrapperW + that.x, that.options.bounce ? that.wrapperW : 0) : momentumX;
547
- momentumY = newPosY ? that._momentum(newPosY - that.startY, duration, -that.y, (that.maxScrollY < 0 ? that.scrollerH - that.wrapperH + that.y - that.minScrollY : 0), that.options.bounce ? that.wrapperH : 0) : momentumY;
548
-
549
- newPosX = that.x + momentumX.dist;
550
- newPosY = that.y + momentumY.dist;
551
-
552
- if ((that.x > 0 && newPosX > 0) || (that.x < that.maxScrollX && newPosX < that.maxScrollX)) momentumX = { dist:0, time:0 };
553
- if ((that.y > that.minScrollY && newPosY > that.minScrollY) || (that.y < that.maxScrollY && newPosY < that.maxScrollY)) momentumY = { dist:0, time:0 };
554
- }
555
-
556
- if (momentumX.dist || momentumY.dist) {
557
- newDuration = m.max(m.max(momentumX.time, momentumY.time), 10);
558
-
559
- // Do we need to snap?
560
- if (that.options.snap) {
561
- distX = newPosX - that.absStartX;
562
- distY = newPosY - that.absStartY;
563
- if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) { that.scrollTo(that.absStartX, that.absStartY, 200); }
564
- else {
565
- snap = that._snap(newPosX, newPosY);
566
- newPosX = snap.x;
567
- newPosY = snap.y;
568
- newDuration = m.max(snap.time, newDuration);
569
- }
570
- }
571
-
572
- that.scrollTo(mround(newPosX), mround(newPosY), newDuration);
573
-
574
- if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
575
- return;
576
- }
577
-
578
- // Do we need to snap?
579
- if (that.options.snap) {
580
- distX = newPosX - that.absStartX;
581
- distY = newPosY - that.absStartY;
582
- if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) that.scrollTo(that.absStartX, that.absStartY, 200);
583
- else {
584
- snap = that._snap(that.x, that.y);
585
- if (snap.x != that.x || snap.y != that.y) that.scrollTo(snap.x, snap.y, snap.time);
586
- }
587
-
588
- if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
589
- return;
590
- }
591
-
592
- that._resetPos(200);
593
- if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
594
- },
595
-
596
- _resetPos: function (time) {
597
- var that = this,
598
- resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,
599
- resetY = that.y >= that.minScrollY || that.maxScrollY > 0 ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;
600
-
601
- if (resetX == that.x && resetY == that.y) {
602
- if (that.moved) {
603
- that.moved = false;
604
- if (that.options.onScrollEnd) that.options.onScrollEnd.call(that); // Execute custom code on scroll end
605
- }
606
-
607
- if (that.hScrollbar && that.options.hideScrollbar) {
608
- if (vendor == 'webkit') that.hScrollbarWrapper.style[vendor + 'TransitionDelay'] = '300ms';
609
- that.hScrollbarWrapper.style.opacity = '0';
610
- }
611
- if (that.vScrollbar && that.options.hideScrollbar) {
612
- if (vendor == 'webkit') that.vScrollbarWrapper.style[vendor + 'TransitionDelay'] = '300ms';
613
- that.vScrollbarWrapper.style.opacity = '0';
614
- }
615
-
616
- return;
617
- }
618
-
619
- that.scrollTo(resetX, resetY, time || 0);
620
- },
621
-
622
- _wheel: function (e) {
623
- var that = this,
624
- wheelDeltaX, wheelDeltaY,
625
- deltaX, deltaY,
626
- deltaScale;
627
-
628
- if ('wheelDeltaX' in e) {
629
- wheelDeltaX = e.wheelDeltaX / 12;
630
- wheelDeltaY = e.wheelDeltaY / 12;
631
- } else if('wheelDelta' in e) {
632
- wheelDeltaX = wheelDeltaY = e.wheelDelta / 12;
633
- } else if ('detail' in e) {
634
- wheelDeltaX = wheelDeltaY = -e.detail * 3;
635
- } else {
636
- return;
637
- }
638
-
639
- if (that.options.wheelAction == 'zoom') {
640
- deltaScale = that.scale * Math.pow(2, 1/3 * (wheelDeltaY ? wheelDeltaY / Math.abs(wheelDeltaY) : 0));
641
- if (deltaScale < that.options.zoomMin) deltaScale = that.options.zoomMin;
642
- if (deltaScale > that.options.zoomMax) deltaScale = that.options.zoomMax;
643
-
644
- if (deltaScale != that.scale) {
645
- if (!that.wheelZoomCount && that.options.onZoomStart) that.options.onZoomStart.call(that, e);
646
- that.wheelZoomCount++;
647
-
648
- that.zoom(e.pageX, e.pageY, deltaScale, 400);
649
-
650
- setTimeout(function() {
651
- that.wheelZoomCount--;
652
- if (!that.wheelZoomCount && that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);
653
- }, 400);
654
- }
655
-
656
- return;
657
- }
658
-
659
- deltaX = that.x + wheelDeltaX;
660
- deltaY = that.y + wheelDeltaY;
661
-
662
- if (deltaX > 0) deltaX = 0;
663
- else if (deltaX < that.maxScrollX) deltaX = that.maxScrollX;
664
-
665
- if (deltaY > that.minScrollY) deltaY = that.minScrollY;
666
- else if (deltaY < that.maxScrollY) deltaY = that.maxScrollY;
667
-
668
- that.scrollTo(deltaX, deltaY, 0);
669
- },
670
-
671
- _mouseout: function (e) {
672
- var t = e.relatedTarget;
673
-
674
- if (!t) {
675
- this._end(e);
676
- return;
677
- }
678
-
679
- while (t = t.parentNode) if (t == this.wrapper) return;
680
-
681
- this._end(e);
682
- },
683
-
684
- _transitionEnd: function (e) {
685
- var that = this;
686
-
687
- if (e.target != that.scroller) return;
688
-
689
- that._unbind('webkitTransitionEnd');
690
-
691
- that._startAni();
692
- },
693
-
694
-
695
- /**
696
- *
697
- * Utilities
698
- *
699
- */
700
- _startAni: function () {
701
- var that = this,
702
- startX = that.x, startY = that.y,
703
- startTime = Date.now(),
704
- step, easeOut,
705
- animate;
706
-
707
- if (that.animating) return;
708
-
709
- if (!that.steps.length) {
710
- that._resetPos(400);
711
- return;
712
- }
713
-
714
- step = that.steps.shift();
715
-
716
- if (step.x == startX && step.y == startY) step.time = 0;
717
-
718
- that.animating = true;
719
- that.moved = true;
720
-
721
- if (that.options.useTransition) {
722
- that._transitionTime(step.time);
723
- that._pos(step.x, step.y);
724
- that.animating = false;
725
- if (step.time) that._bind('webkitTransitionEnd');
726
- else that._resetPos(0);
727
- return;
728
- }
729
-
730
- animate = function () {
731
- var now = Date.now(),
732
- newX, newY;
733
-
734
- if (now >= startTime + step.time) {
735
- that._pos(step.x, step.y);
736
- that.animating = false;
737
- if (that.options.onAnimationEnd) that.options.onAnimationEnd.call(that); // Execute custom code on animation end
738
- that._startAni();
739
- return;
740
- }
741
-
742
- now = (now - startTime) / step.time - 1;
743
- easeOut = m.sqrt(1 - now * now);
744
- newX = (step.x - startX) * easeOut + startX;
745
- newY = (step.y - startY) * easeOut + startY;
746
- that._pos(newX, newY);
747
- if (that.animating) that.aniTime = nextFrame(animate);
748
- };
749
-
750
- animate();
751
- },
752
-
753
- _transitionTime: function (time) {
754
- time += 'ms';
755
- this.scroller.style[vendor + 'TransitionDuration'] = time;
756
- if (this.hScrollbar) this.hScrollbarIndicator.style[vendor + 'TransitionDuration'] = time;
757
- if (this.vScrollbar) this.vScrollbarIndicator.style[vendor + 'TransitionDuration'] = time;
758
- },
759
-
760
- _momentum: function (dist, time, maxDistUpper, maxDistLower, size) {
761
- var deceleration = 0.0006,
762
- speed = m.abs(dist) / time,
763
- newDist = (speed * speed) / (2 * deceleration),
764
- newTime = 0, outsideDist = 0;
765
-
766
- // Proportinally reduce speed if we are outside of the boundaries
767
- if (dist > 0 && newDist > maxDistUpper) {
768
- outsideDist = size / (6 / (newDist / speed * deceleration));
769
- maxDistUpper = maxDistUpper + outsideDist;
770
- speed = speed * maxDistUpper / newDist;
771
- newDist = maxDistUpper;
772
- } else if (dist < 0 && newDist > maxDistLower) {
773
- outsideDist = size / (6 / (newDist / speed * deceleration));
774
- maxDistLower = maxDistLower + outsideDist;
775
- speed = speed * maxDistLower / newDist;
776
- newDist = maxDistLower;
777
- }
778
-
779
- newDist = newDist * (dist < 0 ? -1 : 1);
780
- newTime = speed / deceleration;
781
-
782
- return { dist: newDist, time: mround(newTime) };
783
- },
784
-
785
- _offset: function (el) {
786
- var left = -el.offsetLeft,
787
- top = -el.offsetTop;
788
-
789
- while (el = el.offsetParent) {
790
- left -= el.offsetLeft;
791
- top -= el.offsetTop;
792
- }
793
-
794
- if (el != this.wrapper) {
795
- left *= this.scale;
796
- top *= this.scale;
797
- }
798
-
799
- return { left: left, top: top };
800
- },
801
-
802
- _snap: function (x, y) {
803
- var that = this,
804
- i, l,
805
- page, time,
806
- sizeX, sizeY;
807
-
808
- // Check page X
809
- page = that.pagesX.length - 1;
810
- for (i=0, l=that.pagesX.length; i<l; i++) {
811
- if (x >= that.pagesX[i]) {
812
- page = i;
813
- break;
814
- }
815
- }
816
- if (page == that.currPageX && page > 0 && that.dirX < 0) page--;
817
- x = that.pagesX[page];
818
- sizeX = m.abs(x - that.pagesX[that.currPageX]);
819
- sizeX = sizeX ? m.abs(that.x - x) / sizeX * 500 : 0;
820
- that.currPageX = page;
821
-
822
- // Check page Y
823
- page = that.pagesY.length-1;
824
- for (i=0; i<page; i++) {
825
- if (y >= that.pagesY[i]) {
826
- page = i;
827
- break;
828
- }
829
- }
830
- if (page == that.currPageY && page > 0 && that.dirY < 0) page--;
831
- y = that.pagesY[page];
832
- sizeY = m.abs(y - that.pagesY[that.currPageY]);
833
- sizeY = sizeY ? m.abs(that.y - y) / sizeY * 500 : 0;
834
- that.currPageY = page;
835
-
836
- // Snap with constant speed (proportional duration)
837
- time = mround(m.max(sizeX, sizeY)) || 200;
838
-
839
- return { x: x, y: y, time: time };
840
- },
841
-
842
- _bind: function (type, el, bubble) {
843
- (el || this.scroller).addEventListener(type, this, !!bubble);
844
- },
845
-
846
- _unbind: function (type, el, bubble) {
847
- (el || this.scroller).removeEventListener(type, this, !!bubble);
848
- },
849
-
850
-
851
- /**
852
- *
853
- * Public methods
854
- *
855
- */
856
- destroy: function () {
857
- var that = this;
858
-
859
- that.scroller.style[vendor + 'Transform'] = '';
860
-
861
- // Remove the scrollbars
862
- that.hScrollbar = false;
863
- that.vScrollbar = false;
864
- that._scrollbar('h');
865
- that._scrollbar('v');
866
-
867
- // Remove the event listeners
868
- that._unbind(RESIZE_EV, window);
869
- that._unbind(START_EV);
870
- that._unbind(MOVE_EV);
871
- that._unbind(END_EV);
872
- that._unbind(CANCEL_EV);
873
-
874
- if (!that.options.hasTouch) {
875
- that._unbind('mouseout', that.wrapper);
876
- that._unbind(WHEEL_EV);
877
- }
878
-
879
- if (that.options.useTransition) that._unbind('webkitTransitionEnd');
880
-
881
- if (that.options.checkDOMChanges) clearInterval(that.checkDOMTime);
882
-
883
- if (that.options.onDestroy) that.options.onDestroy.call(that);
884
- },
885
-
886
- refresh: function () {
887
- var that = this,
888
- offset,
889
- i, l,
890
- els,
891
- pos = 0,
892
- page = 0;
893
-
894
- if (that.scale < that.options.zoomMin) that.scale = that.options.zoomMin;
895
- that.wrapperW = that.wrapper.clientWidth || 1;
896
- that.wrapperH = that.wrapper.clientHeight || 1;
897
-
898
- that.minScrollY = -that.options.topOffset || 0;
899
- that.scrollerW = mround(that.scroller.offsetWidth * that.scale);
900
- that.scrollerH = mround((that.scroller.offsetHeight + that.minScrollY) * that.scale);
901
- that.maxScrollX = that.wrapperW - that.scrollerW;
902
- that.maxScrollY = that.wrapperH - that.scrollerH + that.minScrollY;
903
- that.dirX = 0;
904
- that.dirY = 0;
905
-
906
- if (that.options.onRefresh) that.options.onRefresh.call(that);
907
-
908
- that.hScroll = that.options.hScroll && that.maxScrollX < 0;
909
- that.vScroll = that.options.vScroll && (!that.options.bounceLock && !that.hScroll || that.scrollerH > that.wrapperH);
910
-
911
- that.hScrollbar = that.hScroll && that.options.hScrollbar;
912
- that.vScrollbar = that.vScroll && that.options.vScrollbar && that.scrollerH > that.wrapperH;
913
-
914
- offset = that._offset(that.wrapper);
915
- that.wrapperOffsetLeft = -offset.left;
916
- that.wrapperOffsetTop = -offset.top;
917
-
918
- // Prepare snap
919
- if (typeof that.options.snap == 'string') {
920
- that.pagesX = [];
921
- that.pagesY = [];
922
- els = that.scroller.querySelectorAll(that.options.snap);
923
- for (i=0, l=els.length; i<l; i++) {
924
- pos = that._offset(els[i]);
925
- pos.left += that.wrapperOffsetLeft;
926
- pos.top += that.wrapperOffsetTop;
927
- that.pagesX[i] = pos.left < that.maxScrollX ? that.maxScrollX : pos.left * that.scale;
928
- that.pagesY[i] = pos.top < that.maxScrollY ? that.maxScrollY : pos.top * that.scale;
929
- }
930
- } else if (that.options.snap) {
931
- that.pagesX = [];
932
- while (pos >= that.maxScrollX) {
933
- that.pagesX[page] = pos;
934
- pos = pos - that.wrapperW;
935
- page++;
936
- }
937
- if (that.maxScrollX%that.wrapperW) that.pagesX[that.pagesX.length] = that.maxScrollX - that.pagesX[that.pagesX.length-1] + that.pagesX[that.pagesX.length-1];
938
-
939
- pos = 0;
940
- page = 0;
941
- that.pagesY = [];
942
- while (pos >= that.maxScrollY) {
943
- that.pagesY[page] = pos;
944
- pos = pos - that.wrapperH;
945
- page++;
946
- }
947
- if (that.maxScrollY%that.wrapperH) that.pagesY[that.pagesY.length] = that.maxScrollY - that.pagesY[that.pagesY.length-1] + that.pagesY[that.pagesY.length-1];
948
- }
949
-
950
- // Prepare the scrollbars
951
- that._scrollbar('h');
952
- that._scrollbar('v');
953
-
954
- if (!that.zoomed) {
955
- that.scroller.style[vendor + 'TransitionDuration'] = '0';
956
- //that._resetPos(200);
957
- that._resetPos(0);
958
- }
959
- },
960
-
961
- scrollTo: function (x, y, time, relative) {
962
- var that = this,
963
- step = x,
964
- i, l;
965
-
966
- that.stop();
967
-
968
- if (!step.length) step = [{ x: x, y: y, time: time, relative: relative }];
969
-
970
- for (i=0, l=step.length; i<l; i++) {
971
- if (step[i].relative) { step[i].x = that.x - step[i].x; step[i].y = that.y - step[i].y; }
972
- that.steps.push({ x: step[i].x, y: step[i].y, time: step[i].time || 0 });
973
- }
974
-
975
- that._startAni();
976
- },
977
-
978
- scrollToElement: function (el, time) {
979
- var that = this, pos;
980
- el = el.nodeType ? el : that.scroller.querySelector(el);
981
- if (!el) return;
982
-
983
- pos = that._offset(el);
984
- pos.left += that.wrapperOffsetLeft;
985
- pos.top += that.wrapperOffsetTop;
986
-
987
- pos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;
988
- pos.top = pos.top > that.minScrollY ? that.minScrollY : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;
989
- time = time === undefined ? m.max(m.abs(pos.left)*2, m.abs(pos.top)*2) : time;
990
-
991
- that.scrollTo(pos.left, pos.top, time);
992
- },
993
-
994
- scrollToPage: function (pageX, pageY, time) {
995
- var that = this, x, y;
996
-
997
- time = time === undefined ? 400 : time;
998
-
999
- if (that.options.onScrollStart) that.options.onScrollStart.call(that);
1000
-
1001
- if (that.options.snap) {
1002
- pageX = pageX == 'next' ? that.currPageX+1 : pageX == 'prev' ? that.currPageX-1 : pageX;
1003
- pageY = pageY == 'next' ? that.currPageY+1 : pageY == 'prev' ? that.currPageY-1 : pageY;
1004
-
1005
- pageX = pageX < 0 ? 0 : pageX > that.pagesX.length-1 ? that.pagesX.length-1 : pageX;
1006
- pageY = pageY < 0 ? 0 : pageY > that.pagesY.length-1 ? that.pagesY.length-1 : pageY;
1007
-
1008
- that.currPageX = pageX;
1009
- that.currPageY = pageY;
1010
- x = that.pagesX[pageX];
1011
- y = that.pagesY[pageY];
1012
- } else {
1013
- x = -that.wrapperW * pageX;
1014
- y = -that.wrapperH * pageY;
1015
- if (x < that.maxScrollX) x = that.maxScrollX;
1016
- if (y < that.maxScrollY) y = that.maxScrollY;
1017
- }
1018
-
1019
- that.scrollTo(x, y, time);
1020
- },
1021
-
1022
- disable: function () {
1023
- this.stop();
1024
- this._resetPos(0);
1025
- this.enabled = false;
1026
-
1027
- // If disabled after touchstart we make sure that there are no left over events
1028
- this._unbind(MOVE_EV);
1029
- this._unbind(END_EV);
1030
- this._unbind(CANCEL_EV);
1031
- },
1032
-
1033
- enable: function () {
1034
- this.enabled = true;
1035
- },
1036
-
1037
- stop: function () {
1038
- if (this.options.useTransition) this._unbind('webkitTransitionEnd');
1039
- else cancelFrame(this.aniTime);
1040
- this.steps = [];
1041
- this.moved = false;
1042
- this.animating = false;
1043
- },
1044
-
1045
- zoom: function (x, y, scale, time) {
1046
- var that = this,
1047
- relScale = scale / that.scale;
1048
-
1049
- if (!that.options.useTransform) return;
1050
-
1051
- that.zoomed = true;
1052
- time = time === undefined ? 200 : time;
1053
- x = x - that.wrapperOffsetLeft - that.x;
1054
- y = y - that.wrapperOffsetTop - that.y;
1055
- that.x = x - x * relScale + that.x;
1056
- that.y = y - y * relScale + that.y;
1057
-
1058
- that.scale = scale;
1059
- that.refresh();
1060
-
1061
- that.x = that.x > 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x;
1062
- that.y = that.y > that.minScrollY ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;
1063
-
1064
- that.scroller.style[vendor + 'TransitionDuration'] = time + 'ms';
1065
- that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose + ' scale(' + scale + ')';
1066
- that.zoomed = false;
1067
- },
1068
-
1069
- isReady: function () {
1070
- return !this.moved && !this.zoomed && !this.animating;
1071
- }
1072
- };
1073
-
1074
- if (typeof exports !== 'undefined') exports.iScroll = iScroll;
1075
- else window.iScroll = iScroll;
1076
-
1077
- })();
1078
-
1079
- document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
1080
-
1
+ /*!
2
+ * iScroll v4.2.5 ~ Copyright (c) 2012 Matteo Spinelli, http://cubiq.org
3
+ * Released under MIT license, http://cubiq.org/license
4
+ */
5
+ (function(window, doc){
6
+ var m = Math,
7
+ dummyStyle = doc.createElement('div').style,
8
+ vendor = (function () {
9
+ var vendors = 't,webkitT,MozT,msT,OT'.split(','),
10
+ t,
11
+ i = 0,
12
+ l = vendors.length;
13
+
14
+ for ( ; i < l; i++ ) {
15
+ t = vendors[i] + 'ransform';
16
+ if ( t in dummyStyle ) {
17
+ return vendors[i].substr(0, vendors[i].length - 1);
18
+ }
19
+ }
20
+
21
+ return false;
22
+ })(),
23
+ cssVendor = vendor ? '-' + vendor.toLowerCase() + '-' : '',
24
+
25
+ // Style properties
26
+ transform = prefixStyle('transform'),
27
+ transitionProperty = prefixStyle('transitionProperty'),
28
+ transitionDuration = prefixStyle('transitionDuration'),
29
+ transformOrigin = prefixStyle('transformOrigin'),
30
+ transitionTimingFunction = prefixStyle('transitionTimingFunction'),
31
+ transitionDelay = prefixStyle('transitionDelay'),
32
+
33
+ // Browser capabilities
34
+ isAndroid = (/android/gi).test(navigator.appVersion),
35
+ isIDevice = (/iphone|ipad/gi).test(navigator.appVersion),
36
+ isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),
37
+
38
+ has3d = prefixStyle('perspective') in dummyStyle,
39
+ hasTouch = 'ontouchstart' in window && !isTouchPad,
40
+ hasTransform = vendor !== false,
41
+ hasTransitionEnd = prefixStyle('transition') in dummyStyle,
42
+
43
+ RESIZE_EV = 'onorientationchange' in window ? 'orientationchange' : 'resize',
44
+ START_EV = hasTouch ? 'touchstart' : 'mousedown',
45
+ MOVE_EV = hasTouch ? 'touchmove' : 'mousemove',
46
+ END_EV = hasTouch ? 'touchend' : 'mouseup',
47
+ CANCEL_EV = hasTouch ? 'touchcancel' : 'mouseup',
48
+ TRNEND_EV = (function () {
49
+ if ( vendor === false ) return false;
50
+
51
+ var transitionEnd = {
52
+ '' : 'transitionend',
53
+ 'webkit' : 'webkitTransitionEnd',
54
+ 'Moz' : 'transitionend',
55
+ 'O' : 'otransitionend',
56
+ 'ms' : 'MSTransitionEnd'
57
+ };
58
+
59
+ return transitionEnd[vendor];
60
+ })(),
61
+
62
+ nextFrame = (function() {
63
+ return window.requestAnimationFrame ||
64
+ window.webkitRequestAnimationFrame ||
65
+ window.mozRequestAnimationFrame ||
66
+ window.oRequestAnimationFrame ||
67
+ window.msRequestAnimationFrame ||
68
+ function(callback) { return setTimeout(callback, 1); };
69
+ })(),
70
+ cancelFrame = (function () {
71
+ return window.cancelRequestAnimationFrame ||
72
+ window.webkitCancelAnimationFrame ||
73
+ window.webkitCancelRequestAnimationFrame ||
74
+ window.mozCancelRequestAnimationFrame ||
75
+ window.oCancelRequestAnimationFrame ||
76
+ window.msCancelRequestAnimationFrame ||
77
+ clearTimeout;
78
+ })(),
79
+
80
+ // Helpers
81
+ translateZ = has3d ? ' translateZ(0)' : '',
82
+
83
+ // Constructor
84
+ iScroll = function (el, options) {
85
+ var that = this,
86
+ i;
87
+
88
+ that.wrapper = typeof el == 'object' ? el : doc.getElementById(el);
89
+ that.wrapper.style.overflow = 'hidden';
90
+ that.scroller = that.wrapper.children[0];
91
+
92
+ // Default options
93
+ that.options = {
94
+ hScroll: true,
95
+ vScroll: true,
96
+ x: 0,
97
+ y: 0,
98
+ bounce: true,
99
+ bounceLock: false,
100
+ momentum: true,
101
+ lockDirection: true,
102
+ useTransform: true,
103
+ useTransition: false,
104
+ topOffset: 0,
105
+ checkDOMChanges: false, // Experimental
106
+ handleClick: true,
107
+
108
+ // Scrollbar
109
+ hScrollbar: true,
110
+ vScrollbar: true,
111
+ fixedScrollbar: isAndroid,
112
+ hideScrollbar: isIDevice,
113
+ fadeScrollbar: isIDevice && has3d,
114
+ scrollbarClass: '',
115
+
116
+ // Zoom
117
+ zoom: false,
118
+ zoomMin: 1,
119
+ zoomMax: 4,
120
+ doubleTapZoom: 2,
121
+ wheelAction: 'scroll',
122
+
123
+ // Snap
124
+ snap: false,
125
+ snapThreshold: 1,
126
+
127
+ // Events
128
+ onRefresh: null,
129
+ onBeforeScrollStart: function (e) { e.preventDefault(); },
130
+ onScrollStart: null,
131
+ onBeforeScrollMove: null,
132
+ onScrollMove: null,
133
+ onBeforeScrollEnd: null,
134
+ onScrollEnd: null,
135
+ onTouchEnd: null,
136
+ onDestroy: null,
137
+ onZoomStart: null,
138
+ onZoom: null,
139
+ onZoomEnd: null
140
+ };
141
+
142
+ // User defined options
143
+ for (i in options) that.options[i] = options[i];
144
+
145
+ // Set starting position
146
+ that.x = that.options.x;
147
+ that.y = that.options.y;
148
+
149
+ // Normalize options
150
+ that.options.useTransform = hasTransform && that.options.useTransform;
151
+ that.options.hScrollbar = that.options.hScroll && that.options.hScrollbar;
152
+ that.options.vScrollbar = that.options.vScroll && that.options.vScrollbar;
153
+ that.options.zoom = that.options.useTransform && that.options.zoom;
154
+ that.options.useTransition = hasTransitionEnd && that.options.useTransition;
155
+
156
+ // Helpers FIX ANDROID BUG!
157
+ // translate3d and scale doesn't work together!
158
+ // Ignoring 3d ONLY WHEN YOU SET that.options.zoom
159
+ if ( that.options.zoom && isAndroid ){
160
+ translateZ = '';
161
+ }
162
+
163
+ // Set some default styles
164
+ that.scroller.style[transitionProperty] = that.options.useTransform ? cssVendor + 'transform' : 'top left';
165
+ that.scroller.style[transitionDuration] = '0';
166
+ that.scroller.style[transformOrigin] = '0 0';
167
+ if (that.options.useTransition) that.scroller.style[transitionTimingFunction] = 'cubic-bezier(0.33,0.66,0.66,1)';
168
+
169
+ if (that.options.useTransform) that.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px)' + translateZ;
170
+ else that.scroller.style.cssText += ';position:absolute;top:' + that.y + 'px;left:' + that.x + 'px';
171
+
172
+ if (that.options.useTransition) that.options.fixedScrollbar = true;
173
+
174
+ that.refresh();
175
+
176
+ that._bind(RESIZE_EV, window);
177
+ that._bind(START_EV);
178
+ if (!hasTouch) {
179
+ if (that.options.wheelAction != 'none') {
180
+ that._bind('DOMMouseScroll');
181
+ that._bind('mousewheel');
182
+ }
183
+ }
184
+
185
+ if (that.options.checkDOMChanges) that.checkDOMTime = setInterval(function () {
186
+ that._checkDOMChanges();
187
+ }, 500);
188
+ };
189
+
190
+ // Prototype
191
+ iScroll.prototype = {
192
+ enabled: true,
193
+ x: 0,
194
+ y: 0,
195
+ steps: [],
196
+ scale: 1,
197
+ currPageX: 0, currPageY: 0,
198
+ pagesX: [], pagesY: [],
199
+ aniTime: null,
200
+ wheelZoomCount: 0,
201
+
202
+ handleEvent: function (e) {
203
+ var that = this;
204
+ switch(e.type) {
205
+ case START_EV:
206
+ if (!hasTouch && e.button !== 0) return;
207
+ that._start(e);
208
+ break;
209
+ case MOVE_EV: that._move(e); break;
210
+ case END_EV:
211
+ case CANCEL_EV: that._end(e); break;
212
+ case RESIZE_EV: that._resize(); break;
213
+ case 'DOMMouseScroll': case 'mousewheel': that._wheel(e); break;
214
+ case TRNEND_EV: that._transitionEnd(e); break;
215
+ }
216
+ },
217
+
218
+ _checkDOMChanges: function () {
219
+ if (this.moved || this.zoomed || this.animating ||
220
+ (this.scrollerW == this.scroller.offsetWidth * this.scale && this.scrollerH == this.scroller.offsetHeight * this.scale)) return;
221
+
222
+ this.refresh();
223
+ },
224
+
225
+ _scrollbar: function (dir) {
226
+ var that = this,
227
+ bar;
228
+
229
+ if (!that[dir + 'Scrollbar']) {
230
+ if (that[dir + 'ScrollbarWrapper']) {
231
+ if (hasTransform) that[dir + 'ScrollbarIndicator'].style[transform] = '';
232
+ that[dir + 'ScrollbarWrapper'].parentNode.removeChild(that[dir + 'ScrollbarWrapper']);
233
+ that[dir + 'ScrollbarWrapper'] = null;
234
+ that[dir + 'ScrollbarIndicator'] = null;
235
+ }
236
+
237
+ return;
238
+ }
239
+
240
+
241
+ if (!that[dir + 'ScrollbarWrapper']) {
242
+ // Create the scrollbar wrapper
243
+ bar = doc.createElement('div');
244
+
245
+ if (that.options.scrollbarClass) bar.className = that.options.scrollbarClass + dir.toUpperCase();
246
+ else bar.style.cssText = 'position:absolute;z-index:1000;' + (dir == 'h' ? 'height:7px;bottom:1px;left:2px;right:' + (that.vScrollbar ? '7' : '2') + 'px' : 'width:7px;bottom:' + (that.hScrollbar ? '7' : '2') + 'px;top:2px;right:1px');
247
+
248
+ bar.style.cssText += ';pointer-events:none;' + cssVendor + 'transition-property:opacity;' + cssVendor + 'transition-duration:' + (that.options.fadeScrollbar ? '350ms' : '0') + ';overflow:hidden;opacity:' + (that.options.hideScrollbar ? '0' : '1');
249
+
250
+ that.wrapper.appendChild(bar);
251
+ that[dir + 'ScrollbarWrapper'] = bar;
252
+
253
+ // Create the scrollbar indicator
254
+ bar = doc.createElement('div');
255
+ if (!that.options.scrollbarClass) {
256
+ bar.style.cssText = 'position:absolute;z-index:1000;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);' + cssVendor + 'background-clip:padding-box;' + cssVendor + 'box-sizing:border-box;' + (dir == 'h' ? 'height:100%' : 'width:100%') + ';' + cssVendor + 'border-radius:3px;border-radius:3px';
257
+ }
258
+ bar.style.cssText += ';pointer-events:none;' + cssVendor + 'transition-property:' + cssVendor + 'transform;' + cssVendor + 'transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);' + cssVendor + 'transition-duration:0;' + cssVendor + 'transform: translate(0,0)' + translateZ;
259
+ if (that.options.useTransition) bar.style.cssText += ';' + cssVendor + 'transition-timing-function:cubic-bezier(0.33,0.66,0.66,1)';
260
+
261
+ that[dir + 'ScrollbarWrapper'].appendChild(bar);
262
+ that[dir + 'ScrollbarIndicator'] = bar;
263
+ }
264
+
265
+ if (dir == 'h') {
266
+ that.hScrollbarSize = that.hScrollbarWrapper.clientWidth;
267
+ that.hScrollbarIndicatorSize = m.max(m.round(that.hScrollbarSize * that.hScrollbarSize / that.scrollerW), 8);
268
+ that.hScrollbarIndicator.style.width = that.hScrollbarIndicatorSize + 'px';
269
+ that.hScrollbarMaxScroll = that.hScrollbarSize - that.hScrollbarIndicatorSize;
270
+ that.hScrollbarProp = that.hScrollbarMaxScroll / that.maxScrollX;
271
+ } else {
272
+ that.vScrollbarSize = that.vScrollbarWrapper.clientHeight;
273
+ that.vScrollbarIndicatorSize = m.max(m.round(that.vScrollbarSize * that.vScrollbarSize / that.scrollerH), 8);
274
+ that.vScrollbarIndicator.style.height = that.vScrollbarIndicatorSize + 'px';
275
+ that.vScrollbarMaxScroll = that.vScrollbarSize - that.vScrollbarIndicatorSize;
276
+ that.vScrollbarProp = that.vScrollbarMaxScroll / that.maxScrollY;
277
+ }
278
+
279
+ // Reset position
280
+ that._scrollbarPos(dir, true);
281
+ },
282
+
283
+ _resize: function () {
284
+ var that = this;
285
+ setTimeout(function () { that.refresh(); }, isAndroid ? 200 : 0);
286
+ },
287
+
288
+ _pos: function (x, y) {
289
+ if (this.zoomed) return;
290
+
291
+ x = this.hScroll ? x : 0;
292
+ y = this.vScroll ? y : 0;
293
+
294
+ if (this.options.useTransform) {
295
+ this.scroller.style[transform] = 'translate(' + x + 'px,' + y + 'px) scale(' + this.scale + ')' + translateZ;
296
+ } else {
297
+ x = m.round(x);
298
+ y = m.round(y);
299
+ this.scroller.style.left = x + 'px';
300
+ this.scroller.style.top = y + 'px';
301
+ }
302
+
303
+ this.x = x;
304
+ this.y = y;
305
+
306
+ this._scrollbarPos('h');
307
+ this._scrollbarPos('v');
308
+ },
309
+
310
+ _scrollbarPos: function (dir, hidden) {
311
+ var that = this,
312
+ pos = dir == 'h' ? that.x : that.y,
313
+ size;
314
+
315
+ if (!that[dir + 'Scrollbar']) return;
316
+
317
+ pos = that[dir + 'ScrollbarProp'] * pos;
318
+
319
+ if (pos < 0) {
320
+ if (!that.options.fixedScrollbar) {
321
+ size = that[dir + 'ScrollbarIndicatorSize'] + m.round(pos * 3);
322
+ if (size < 8) size = 8;
323
+ that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';
324
+ }
325
+ pos = 0;
326
+ } else if (pos > that[dir + 'ScrollbarMaxScroll']) {
327
+ if (!that.options.fixedScrollbar) {
328
+ size = that[dir + 'ScrollbarIndicatorSize'] - m.round((pos - that[dir + 'ScrollbarMaxScroll']) * 3);
329
+ if (size < 8) size = 8;
330
+ that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';
331
+ pos = that[dir + 'ScrollbarMaxScroll'] + (that[dir + 'ScrollbarIndicatorSize'] - size);
332
+ } else {
333
+ pos = that[dir + 'ScrollbarMaxScroll'];
334
+ }
335
+ }
336
+
337
+ that[dir + 'ScrollbarWrapper'].style[transitionDelay] = '0';
338
+ that[dir + 'ScrollbarWrapper'].style.opacity = hidden && that.options.hideScrollbar ? '0' : '1';
339
+ that[dir + 'ScrollbarIndicator'].style[transform] = 'translate(' + (dir == 'h' ? pos + 'px,0)' : '0,' + pos + 'px)') + translateZ;
340
+ },
341
+
342
+ _start: function (e) {
343
+ var that = this,
344
+ point = hasTouch ? e.touches[0] : e,
345
+ matrix, x, y,
346
+ c1, c2;
347
+
348
+ if (!that.enabled) return;
349
+
350
+ if (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);
351
+
352
+ if (that.options.useTransition || that.options.zoom) that._transitionTime(0);
353
+
354
+ that.moved = false;
355
+ that.animating = false;
356
+ that.zoomed = false;
357
+ that.distX = 0;
358
+ that.distY = 0;
359
+ that.absDistX = 0;
360
+ that.absDistY = 0;
361
+ that.dirX = 0;
362
+ that.dirY = 0;
363
+
364
+ // Gesture start
365
+ if (that.options.zoom && hasTouch && e.touches.length > 1) {
366
+ c1 = m.abs(e.touches[0].pageX-e.touches[1].pageX);
367
+ c2 = m.abs(e.touches[0].pageY-e.touches[1].pageY);
368
+ that.touchesDistStart = m.sqrt(c1 * c1 + c2 * c2);
369
+
370
+ that.originX = m.abs(e.touches[0].pageX + e.touches[1].pageX - that.wrapperOffsetLeft * 2) / 2 - that.x;
371
+ that.originY = m.abs(e.touches[0].pageY + e.touches[1].pageY - that.wrapperOffsetTop * 2) / 2 - that.y;
372
+
373
+ if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);
374
+ }
375
+
376
+ if (that.options.momentum) {
377
+ if (that.options.useTransform) {
378
+ // Very lame general purpose alternative to CSSMatrix
379
+ matrix = getComputedStyle(that.scroller, null)[transform].replace(/[^0-9\-.,]/g, '').split(',');
380
+ x = +(matrix[12] || matrix[4]);
381
+ y = +(matrix[13] || matrix[5]);
382
+ } else {
383
+ x = +getComputedStyle(that.scroller, null).left.replace(/[^0-9-]/g, '');
384
+ y = +getComputedStyle(that.scroller, null).top.replace(/[^0-9-]/g, '');
385
+ }
386
+
387
+ if (x != that.x || y != that.y) {
388
+ if (that.options.useTransition) that._unbind(TRNEND_EV);
389
+ else cancelFrame(that.aniTime);
390
+ that.steps = [];
391
+ that._pos(x, y);
392
+ if (that.options.onScrollEnd) that.options.onScrollEnd.call(that);
393
+ }
394
+ }
395
+
396
+ that.absStartX = that.x; // Needed by snap threshold
397
+ that.absStartY = that.y;
398
+
399
+ that.startX = that.x;
400
+ that.startY = that.y;
401
+ that.pointX = point.pageX;
402
+ that.pointY = point.pageY;
403
+
404
+ that.startTime = e.timeStamp || Date.now();
405
+
406
+ if (that.options.onScrollStart) that.options.onScrollStart.call(that, e);
407
+
408
+ that._bind(MOVE_EV, window);
409
+ that._bind(END_EV, window);
410
+ that._bind(CANCEL_EV, window);
411
+ },
412
+
413
+ _move: function (e) {
414
+ var that = this,
415
+ point = hasTouch ? e.touches[0] : e,
416
+ deltaX = point.pageX - that.pointX,
417
+ deltaY = point.pageY - that.pointY,
418
+ newX = that.x + deltaX,
419
+ newY = that.y + deltaY,
420
+ c1, c2, scale,
421
+ timestamp = e.timeStamp || Date.now();
422
+
423
+ if (that.options.onBeforeScrollMove) that.options.onBeforeScrollMove.call(that, e);
424
+
425
+ // Zoom
426
+ if (that.options.zoom && hasTouch && e.touches.length > 1) {
427
+ c1 = m.abs(e.touches[0].pageX - e.touches[1].pageX);
428
+ c2 = m.abs(e.touches[0].pageY - e.touches[1].pageY);
429
+ that.touchesDist = m.sqrt(c1*c1+c2*c2);
430
+
431
+ that.zoomed = true;
432
+
433
+ scale = 1 / that.touchesDistStart * that.touchesDist * this.scale;
434
+
435
+ if (scale < that.options.zoomMin) scale = 0.5 * that.options.zoomMin * Math.pow(2.0, scale / that.options.zoomMin);
436
+ else if (scale > that.options.zoomMax) scale = 2.0 * that.options.zoomMax * Math.pow(0.5, that.options.zoomMax / scale);
437
+
438
+ that.lastScale = scale / this.scale;
439
+
440
+ newX = this.originX - this.originX * that.lastScale + this.x,
441
+ newY = this.originY - this.originY * that.lastScale + this.y;
442
+
443
+ this.scroller.style[transform] = 'translate(' + newX + 'px,' + newY + 'px) scale(' + scale + ')' + translateZ;
444
+
445
+ if (that.options.onZoom) that.options.onZoom.call(that, e);
446
+ return;
447
+ }
448
+
449
+ that.pointX = point.pageX;
450
+ that.pointY = point.pageY;
451
+
452
+ // Slow down if outside of the boundaries
453
+ if (newX > 0 || newX < that.maxScrollX) {
454
+ newX = that.options.bounce ? that.x + (deltaX / 2) : newX >= 0 || that.maxScrollX >= 0 ? 0 : that.maxScrollX;
455
+ }
456
+ if (newY > that.minScrollY || newY < that.maxScrollY) {
457
+ newY = that.options.bounce ? that.y + (deltaY / 2) : newY >= that.minScrollY || that.maxScrollY >= 0 ? that.minScrollY : that.maxScrollY;
458
+ }
459
+
460
+ that.distX += deltaX;
461
+ that.distY += deltaY;
462
+ that.absDistX = m.abs(that.distX);
463
+ that.absDistY = m.abs(that.distY);
464
+
465
+ if (that.absDistX < 6 && that.absDistY < 6) {
466
+ return;
467
+ }
468
+
469
+ // Lock direction
470
+ if (that.options.lockDirection) {
471
+ if (that.absDistX > that.absDistY + 5) {
472
+ newY = that.y;
473
+ deltaY = 0;
474
+ } else if (that.absDistY > that.absDistX + 5) {
475
+ newX = that.x;
476
+ deltaX = 0;
477
+ }
478
+ }
479
+
480
+ that.moved = true;
481
+ that._pos(newX, newY);
482
+ that.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
483
+ that.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
484
+
485
+ if (timestamp - that.startTime > 300) {
486
+ that.startTime = timestamp;
487
+ that.startX = that.x;
488
+ that.startY = that.y;
489
+ }
490
+
491
+ if (that.options.onScrollMove) that.options.onScrollMove.call(that, e);
492
+ },
493
+
494
+ _end: function (e) {
495
+ if (hasTouch && e.touches.length !== 0) return;
496
+
497
+ var that = this,
498
+ point = hasTouch ? e.changedTouches[0] : e,
499
+ target, ev,
500
+ momentumX = { dist:0, time:0 },
501
+ momentumY = { dist:0, time:0 },
502
+ duration = (e.timeStamp || Date.now()) - that.startTime,
503
+ newPosX = that.x,
504
+ newPosY = that.y,
505
+ distX, distY,
506
+ newDuration,
507
+ snap,
508
+ scale;
509
+
510
+ that._unbind(MOVE_EV, window);
511
+ that._unbind(END_EV, window);
512
+ that._unbind(CANCEL_EV, window);
513
+
514
+ if (that.options.onBeforeScrollEnd) that.options.onBeforeScrollEnd.call(that, e);
515
+
516
+ if (that.zoomed) {
517
+ scale = that.scale * that.lastScale;
518
+ scale = Math.max(that.options.zoomMin, scale);
519
+ scale = Math.min(that.options.zoomMax, scale);
520
+ that.lastScale = scale / that.scale;
521
+ that.scale = scale;
522
+
523
+ that.x = that.originX - that.originX * that.lastScale + that.x;
524
+ that.y = that.originY - that.originY * that.lastScale + that.y;
525
+
526
+ that.scroller.style[transitionDuration] = '200ms';
527
+ that.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px) scale(' + that.scale + ')' + translateZ;
528
+
529
+ that.zoomed = false;
530
+ that.refresh();
531
+
532
+ if (that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);
533
+ return;
534
+ }
535
+
536
+ if (!that.moved) {
537
+ if (hasTouch) {
538
+ if (that.doubleTapTimer && that.options.zoom) {
539
+ // Double tapped
540
+ clearTimeout(that.doubleTapTimer);
541
+ that.doubleTapTimer = null;
542
+ if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);
543
+ that.zoom(that.pointX, that.pointY, that.scale == 1 ? that.options.doubleTapZoom : 1);
544
+ if (that.options.onZoomEnd) {
545
+ setTimeout(function() {
546
+ that.options.onZoomEnd.call(that, e);
547
+ }, 200); // 200 is default zoom duration
548
+ }
549
+ } else if (this.options.handleClick) {
550
+ that.doubleTapTimer = setTimeout(function () {
551
+ that.doubleTapTimer = null;
552
+
553
+ // Find the last touched element
554
+ target = point.target;
555
+ while (target.nodeType != 1) target = target.parentNode;
556
+
557
+ if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
558
+ ev = doc.createEvent('MouseEvents');
559
+ ev.initMouseEvent('click', true, true, e.view, 1,
560
+ point.screenX, point.screenY, point.clientX, point.clientY,
561
+ e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
562
+ 0, null);
563
+ ev._fake = true;
564
+ target.dispatchEvent(ev);
565
+ }
566
+ }, that.options.zoom ? 250 : 0);
567
+ }
568
+ }
569
+
570
+ that._resetPos(400);
571
+
572
+ if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
573
+ return;
574
+ }
575
+
576
+ if (duration < 300 && that.options.momentum) {
577
+ momentumX = newPosX ? that._momentum(newPosX - that.startX, duration, -that.x, that.scrollerW - that.wrapperW + that.x, that.options.bounce ? that.wrapperW : 0) : momentumX;
578
+ momentumY = newPosY ? that._momentum(newPosY - that.startY, duration, -that.y, (that.maxScrollY < 0 ? that.scrollerH - that.wrapperH + that.y - that.minScrollY : 0), that.options.bounce ? that.wrapperH : 0) : momentumY;
579
+
580
+ newPosX = that.x + momentumX.dist;
581
+ newPosY = that.y + momentumY.dist;
582
+
583
+ if ((that.x > 0 && newPosX > 0) || (that.x < that.maxScrollX && newPosX < that.maxScrollX)) momentumX = { dist:0, time:0 };
584
+ if ((that.y > that.minScrollY && newPosY > that.minScrollY) || (that.y < that.maxScrollY && newPosY < that.maxScrollY)) momentumY = { dist:0, time:0 };
585
+ }
586
+
587
+ if (momentumX.dist || momentumY.dist) {
588
+ newDuration = m.max(m.max(momentumX.time, momentumY.time), 10);
589
+
590
+ // Do we need to snap?
591
+ if (that.options.snap) {
592
+ distX = newPosX - that.absStartX;
593
+ distY = newPosY - that.absStartY;
594
+ if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) { that.scrollTo(that.absStartX, that.absStartY, 200); }
595
+ else {
596
+ snap = that._snap(newPosX, newPosY);
597
+ newPosX = snap.x;
598
+ newPosY = snap.y;
599
+ newDuration = m.max(snap.time, newDuration);
600
+ }
601
+ }
602
+
603
+ that.scrollTo(m.round(newPosX), m.round(newPosY), newDuration);
604
+
605
+ if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
606
+ return;
607
+ }
608
+
609
+ // Do we need to snap?
610
+ if (that.options.snap) {
611
+ distX = newPosX - that.absStartX;
612
+ distY = newPosY - that.absStartY;
613
+ if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) that.scrollTo(that.absStartX, that.absStartY, 200);
614
+ else {
615
+ snap = that._snap(that.x, that.y);
616
+ if (snap.x != that.x || snap.y != that.y) that.scrollTo(snap.x, snap.y, snap.time);
617
+ }
618
+
619
+ if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
620
+ return;
621
+ }
622
+
623
+ that._resetPos(200);
624
+ if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
625
+ },
626
+
627
+ _resetPos: function (time) {
628
+ var that = this,
629
+ resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,
630
+ resetY = that.y >= that.minScrollY || that.maxScrollY > 0 ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;
631
+
632
+ if (resetX == that.x && resetY == that.y) {
633
+ if (that.moved) {
634
+ that.moved = false;
635
+ if (that.options.onScrollEnd) that.options.onScrollEnd.call(that); // Execute custom code on scroll end
636
+ }
637
+
638
+ if (that.hScrollbar && that.options.hideScrollbar) {
639
+ if (vendor == 'webkit') that.hScrollbarWrapper.style[transitionDelay] = '300ms';
640
+ that.hScrollbarWrapper.style.opacity = '0';
641
+ }
642
+ if (that.vScrollbar && that.options.hideScrollbar) {
643
+ if (vendor == 'webkit') that.vScrollbarWrapper.style[transitionDelay] = '300ms';
644
+ that.vScrollbarWrapper.style.opacity = '0';
645
+ }
646
+
647
+ return;
648
+ }
649
+
650
+ that.scrollTo(resetX, resetY, time || 0);
651
+ },
652
+
653
+ _wheel: function (e) {
654
+ var that = this,
655
+ wheelDeltaX, wheelDeltaY,
656
+ deltaX, deltaY,
657
+ deltaScale;
658
+
659
+ if ('wheelDeltaX' in e) {
660
+ wheelDeltaX = e.wheelDeltaX / 12;
661
+ wheelDeltaY = e.wheelDeltaY / 12;
662
+ } else if('wheelDelta' in e) {
663
+ wheelDeltaX = wheelDeltaY = e.wheelDelta / 12;
664
+ } else if ('detail' in e) {
665
+ wheelDeltaX = wheelDeltaY = -e.detail * 3;
666
+ } else {
667
+ return;
668
+ }
669
+
670
+ if (that.options.wheelAction == 'zoom') {
671
+ deltaScale = that.scale * Math.pow(2, 1/3 * (wheelDeltaY ? wheelDeltaY / Math.abs(wheelDeltaY) : 0));
672
+ if (deltaScale < that.options.zoomMin) deltaScale = that.options.zoomMin;
673
+ if (deltaScale > that.options.zoomMax) deltaScale = that.options.zoomMax;
674
+
675
+ if (deltaScale != that.scale) {
676
+ if (!that.wheelZoomCount && that.options.onZoomStart) that.options.onZoomStart.call(that, e);
677
+ that.wheelZoomCount++;
678
+
679
+ that.zoom(e.pageX, e.pageY, deltaScale, 400);
680
+
681
+ setTimeout(function() {
682
+ that.wheelZoomCount--;
683
+ if (!that.wheelZoomCount && that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);
684
+ }, 400);
685
+ }
686
+
687
+ return;
688
+ }
689
+
690
+ deltaX = that.x + wheelDeltaX;
691
+ deltaY = that.y + wheelDeltaY;
692
+
693
+ if (deltaX > 0) deltaX = 0;
694
+ else if (deltaX < that.maxScrollX) deltaX = that.maxScrollX;
695
+
696
+ if (deltaY > that.minScrollY) deltaY = that.minScrollY;
697
+ else if (deltaY < that.maxScrollY) deltaY = that.maxScrollY;
698
+
699
+ if (that.maxScrollY < 0) {
700
+ that.scrollTo(deltaX, deltaY, 0);
701
+ }
702
+ },
703
+
704
+ _transitionEnd: function (e) {
705
+ var that = this;
706
+
707
+ if (e.target != that.scroller) return;
708
+
709
+ that._unbind(TRNEND_EV);
710
+
711
+ that._startAni();
712
+ },
713
+
714
+
715
+ /**
716
+ *
717
+ * Utilities
718
+ *
719
+ */
720
+ _startAni: function () {
721
+ var that = this,
722
+ startX = that.x, startY = that.y,
723
+ startTime = Date.now(),
724
+ step, easeOut,
725
+ animate;
726
+
727
+ if (that.animating) return;
728
+
729
+ if (!that.steps.length) {
730
+ that._resetPos(400);
731
+ return;
732
+ }
733
+
734
+ step = that.steps.shift();
735
+
736
+ if (step.x == startX && step.y == startY) step.time = 0;
737
+
738
+ that.animating = true;
739
+ that.moved = true;
740
+
741
+ if (that.options.useTransition) {
742
+ that._transitionTime(step.time);
743
+ that._pos(step.x, step.y);
744
+ that.animating = false;
745
+ if (step.time) that._bind(TRNEND_EV);
746
+ else that._resetPos(0);
747
+ return;
748
+ }
749
+
750
+ animate = function () {
751
+ var now = Date.now(),
752
+ newX, newY;
753
+
754
+ if (now >= startTime + step.time) {
755
+ that._pos(step.x, step.y);
756
+ that.animating = false;
757
+ if (that.options.onAnimationEnd) that.options.onAnimationEnd.call(that); // Execute custom code on animation end
758
+ that._startAni();
759
+ return;
760
+ }
761
+
762
+ now = (now - startTime) / step.time - 1;
763
+ easeOut = m.sqrt(1 - now * now);
764
+ newX = (step.x - startX) * easeOut + startX;
765
+ newY = (step.y - startY) * easeOut + startY;
766
+ that._pos(newX, newY);
767
+ if (that.animating) that.aniTime = nextFrame(animate);
768
+ };
769
+
770
+ animate();
771
+ },
772
+
773
+ _transitionTime: function (time) {
774
+ time += 'ms';
775
+ this.scroller.style[transitionDuration] = time;
776
+ if (this.hScrollbar) this.hScrollbarIndicator.style[transitionDuration] = time;
777
+ if (this.vScrollbar) this.vScrollbarIndicator.style[transitionDuration] = time;
778
+ },
779
+
780
+ _momentum: function (dist, time, maxDistUpper, maxDistLower, size) {
781
+ var deceleration = 0.0006,
782
+ speed = m.abs(dist) / time,
783
+ newDist = (speed * speed) / (2 * deceleration),
784
+ newTime = 0, outsideDist = 0;
785
+
786
+ // Proportinally reduce speed if we are outside of the boundaries
787
+ if (dist > 0 && newDist > maxDistUpper) {
788
+ outsideDist = size / (6 / (newDist / speed * deceleration));
789
+ maxDistUpper = maxDistUpper + outsideDist;
790
+ speed = speed * maxDistUpper / newDist;
791
+ newDist = maxDistUpper;
792
+ } else if (dist < 0 && newDist > maxDistLower) {
793
+ outsideDist = size / (6 / (newDist / speed * deceleration));
794
+ maxDistLower = maxDistLower + outsideDist;
795
+ speed = speed * maxDistLower / newDist;
796
+ newDist = maxDistLower;
797
+ }
798
+
799
+ newDist = newDist * (dist < 0 ? -1 : 1);
800
+ newTime = speed / deceleration;
801
+
802
+ return { dist: newDist, time: m.round(newTime) };
803
+ },
804
+
805
+ _offset: function (el) {
806
+ var left = -el.offsetLeft,
807
+ top = -el.offsetTop;
808
+
809
+ while (el = el.offsetParent) {
810
+ left -= el.offsetLeft;
811
+ top -= el.offsetTop;
812
+ }
813
+
814
+ if (el != this.wrapper) {
815
+ left *= this.scale;
816
+ top *= this.scale;
817
+ }
818
+
819
+ return { left: left, top: top };
820
+ },
821
+
822
+ _snap: function (x, y) {
823
+ var that = this,
824
+ i, l,
825
+ page, time,
826
+ sizeX, sizeY;
827
+
828
+ // Check page X
829
+ page = that.pagesX.length - 1;
830
+ for (i=0, l=that.pagesX.length; i<l; i++) {
831
+ if (x >= that.pagesX[i]) {
832
+ page = i;
833
+ break;
834
+ }
835
+ }
836
+ if (page == that.currPageX && page > 0 && that.dirX < 0) page--;
837
+ x = that.pagesX[page];
838
+ sizeX = m.abs(x - that.pagesX[that.currPageX]);
839
+ sizeX = sizeX ? m.abs(that.x - x) / sizeX * 500 : 0;
840
+ that.currPageX = page;
841
+
842
+ // Check page Y
843
+ page = that.pagesY.length-1;
844
+ for (i=0; i<page; i++) {
845
+ if (y >= that.pagesY[i]) {
846
+ page = i;
847
+ break;
848
+ }
849
+ }
850
+ if (page == that.currPageY && page > 0 && that.dirY < 0) page--;
851
+ y = that.pagesY[page];
852
+ sizeY = m.abs(y - that.pagesY[that.currPageY]);
853
+ sizeY = sizeY ? m.abs(that.y - y) / sizeY * 500 : 0;
854
+ that.currPageY = page;
855
+
856
+ // Snap with constant speed (proportional duration)
857
+ time = m.round(m.max(sizeX, sizeY)) || 200;
858
+
859
+ return { x: x, y: y, time: time };
860
+ },
861
+
862
+ _bind: function (type, el, bubble) {
863
+ (el || this.scroller).addEventListener(type, this, !!bubble);
864
+ },
865
+
866
+ _unbind: function (type, el, bubble) {
867
+ (el || this.scroller).removeEventListener(type, this, !!bubble);
868
+ },
869
+
870
+
871
+ /**
872
+ *
873
+ * Public methods
874
+ *
875
+ */
876
+ destroy: function () {
877
+ var that = this;
878
+
879
+ that.scroller.style[transform] = '';
880
+
881
+ // Remove the scrollbars
882
+ that.hScrollbar = false;
883
+ that.vScrollbar = false;
884
+ that._scrollbar('h');
885
+ that._scrollbar('v');
886
+
887
+ // Remove the event listeners
888
+ that._unbind(RESIZE_EV, window);
889
+ that._unbind(START_EV);
890
+ that._unbind(MOVE_EV, window);
891
+ that._unbind(END_EV, window);
892
+ that._unbind(CANCEL_EV, window);
893
+
894
+ if (!that.options.hasTouch) {
895
+ that._unbind('DOMMouseScroll');
896
+ that._unbind('mousewheel');
897
+ }
898
+
899
+ if (that.options.useTransition) that._unbind(TRNEND_EV);
900
+
901
+ if (that.options.checkDOMChanges) clearInterval(that.checkDOMTime);
902
+
903
+ if (that.options.onDestroy) that.options.onDestroy.call(that);
904
+ },
905
+
906
+ refresh: function () {
907
+ var that = this,
908
+ offset,
909
+ i, l,
910
+ els,
911
+ pos = 0,
912
+ page = 0;
913
+
914
+ if (that.scale < that.options.zoomMin) that.scale = that.options.zoomMin;
915
+ that.wrapperW = that.wrapper.clientWidth || 1;
916
+ that.wrapperH = that.wrapper.clientHeight || 1;
917
+
918
+ that.minScrollY = -that.options.topOffset || 0;
919
+ that.scrollerW = m.round(that.scroller.offsetWidth * that.scale);
920
+ that.scrollerH = m.round((that.scroller.offsetHeight + that.minScrollY) * that.scale);
921
+ that.maxScrollX = that.wrapperW - that.scrollerW;
922
+ that.maxScrollY = that.wrapperH - that.scrollerH + that.minScrollY;
923
+ that.dirX = 0;
924
+ that.dirY = 0;
925
+
926
+ if (that.options.onRefresh) that.options.onRefresh.call(that);
927
+
928
+ that.hScroll = that.options.hScroll && that.maxScrollX < 0;
929
+ that.vScroll = that.options.vScroll && (!that.options.bounceLock && !that.hScroll || that.scrollerH > that.wrapperH);
930
+
931
+ that.hScrollbar = that.hScroll && that.options.hScrollbar;
932
+ that.vScrollbar = that.vScroll && that.options.vScrollbar && that.scrollerH > that.wrapperH;
933
+
934
+ offset = that._offset(that.wrapper);
935
+ that.wrapperOffsetLeft = -offset.left;
936
+ that.wrapperOffsetTop = -offset.top;
937
+
938
+ // Prepare snap
939
+ if (typeof that.options.snap == 'string') {
940
+ that.pagesX = [];
941
+ that.pagesY = [];
942
+ els = that.scroller.querySelectorAll(that.options.snap);
943
+ for (i=0, l=els.length; i<l; i++) {
944
+ pos = that._offset(els[i]);
945
+ pos.left += that.wrapperOffsetLeft;
946
+ pos.top += that.wrapperOffsetTop;
947
+ that.pagesX[i] = pos.left < that.maxScrollX ? that.maxScrollX : pos.left * that.scale;
948
+ that.pagesY[i] = pos.top < that.maxScrollY ? that.maxScrollY : pos.top * that.scale;
949
+ }
950
+ } else if (that.options.snap) {
951
+ that.pagesX = [];
952
+ while (pos >= that.maxScrollX) {
953
+ that.pagesX[page] = pos;
954
+ pos = pos - that.wrapperW;
955
+ page++;
956
+ }
957
+ if (that.maxScrollX%that.wrapperW) that.pagesX[that.pagesX.length] = that.maxScrollX - that.pagesX[that.pagesX.length-1] + that.pagesX[that.pagesX.length-1];
958
+
959
+ pos = 0;
960
+ page = 0;
961
+ that.pagesY = [];
962
+ while (pos >= that.maxScrollY) {
963
+ that.pagesY[page] = pos;
964
+ pos = pos - that.wrapperH;
965
+ page++;
966
+ }
967
+ if (that.maxScrollY%that.wrapperH) that.pagesY[that.pagesY.length] = that.maxScrollY - that.pagesY[that.pagesY.length-1] + that.pagesY[that.pagesY.length-1];
968
+ }
969
+
970
+ // Prepare the scrollbars
971
+ that._scrollbar('h');
972
+ that._scrollbar('v');
973
+
974
+ if (!that.zoomed) {
975
+ that.scroller.style[transitionDuration] = '0';
976
+ that._resetPos(400);
977
+ }
978
+ },
979
+
980
+ scrollTo: function (x, y, time, relative) {
981
+ var that = this,
982
+ step = x,
983
+ i, l;
984
+
985
+ that.stop();
986
+
987
+ if (!step.length) step = [{ x: x, y: y, time: time, relative: relative }];
988
+
989
+ for (i=0, l=step.length; i<l; i++) {
990
+ if (step[i].relative) { step[i].x = that.x - step[i].x; step[i].y = that.y - step[i].y; }
991
+ that.steps.push({ x: step[i].x, y: step[i].y, time: step[i].time || 0 });
992
+ }
993
+
994
+ that._startAni();
995
+ },
996
+
997
+ scrollToElement: function (el, time) {
998
+ var that = this, pos;
999
+ el = el.nodeType ? el : that.scroller.querySelector(el);
1000
+ if (!el) return;
1001
+
1002
+ pos = that._offset(el);
1003
+ pos.left += that.wrapperOffsetLeft;
1004
+ pos.top += that.wrapperOffsetTop;
1005
+
1006
+ pos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;
1007
+ pos.top = pos.top > that.minScrollY ? that.minScrollY : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;
1008
+ time = time === undefined ? m.max(m.abs(pos.left)*2, m.abs(pos.top)*2) : time;
1009
+
1010
+ that.scrollTo(pos.left, pos.top, time);
1011
+ },
1012
+
1013
+ scrollToPage: function (pageX, pageY, time) {
1014
+ var that = this, x, y;
1015
+
1016
+ time = time === undefined ? 400 : time;
1017
+
1018
+ if (that.options.onScrollStart) that.options.onScrollStart.call(that);
1019
+
1020
+ if (that.options.snap) {
1021
+ pageX = pageX == 'next' ? that.currPageX+1 : pageX == 'prev' ? that.currPageX-1 : pageX;
1022
+ pageY = pageY == 'next' ? that.currPageY+1 : pageY == 'prev' ? that.currPageY-1 : pageY;
1023
+
1024
+ pageX = pageX < 0 ? 0 : pageX > that.pagesX.length-1 ? that.pagesX.length-1 : pageX;
1025
+ pageY = pageY < 0 ? 0 : pageY > that.pagesY.length-1 ? that.pagesY.length-1 : pageY;
1026
+
1027
+ that.currPageX = pageX;
1028
+ that.currPageY = pageY;
1029
+ x = that.pagesX[pageX];
1030
+ y = that.pagesY[pageY];
1031
+ } else {
1032
+ x = -that.wrapperW * pageX;
1033
+ y = -that.wrapperH * pageY;
1034
+ if (x < that.maxScrollX) x = that.maxScrollX;
1035
+ if (y < that.maxScrollY) y = that.maxScrollY;
1036
+ }
1037
+
1038
+ that.scrollTo(x, y, time);
1039
+ },
1040
+
1041
+ disable: function () {
1042
+ this.stop();
1043
+ this._resetPos(0);
1044
+ this.enabled = false;
1045
+
1046
+ // If disabled after touchstart we make sure that there are no left over events
1047
+ this._unbind(MOVE_EV, window);
1048
+ this._unbind(END_EV, window);
1049
+ this._unbind(CANCEL_EV, window);
1050
+ },
1051
+
1052
+ enable: function () {
1053
+ this.enabled = true;
1054
+ },
1055
+
1056
+ stop: function () {
1057
+ if (this.options.useTransition) this._unbind(TRNEND_EV);
1058
+ else cancelFrame(this.aniTime);
1059
+ this.steps = [];
1060
+ this.moved = false;
1061
+ this.animating = false;
1062
+ },
1063
+
1064
+ zoom: function (x, y, scale, time) {
1065
+ var that = this,
1066
+ relScale = scale / that.scale;
1067
+
1068
+ if (!that.options.useTransform) return;
1069
+
1070
+ that.zoomed = true;
1071
+ time = time === undefined ? 200 : time;
1072
+ x = x - that.wrapperOffsetLeft - that.x;
1073
+ y = y - that.wrapperOffsetTop - that.y;
1074
+ that.x = x - x * relScale + that.x;
1075
+ that.y = y - y * relScale + that.y;
1076
+
1077
+ that.scale = scale;
1078
+ that.refresh();
1079
+
1080
+ that.x = that.x > 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x;
1081
+ that.y = that.y > that.minScrollY ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;
1082
+
1083
+ that.scroller.style[transitionDuration] = time + 'ms';
1084
+ that.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px) scale(' + scale + ')' + translateZ;
1085
+ that.zoomed = false;
1086
+ },
1087
+
1088
+ isReady: function () {
1089
+ return !this.moved && !this.zoomed && !this.animating;
1090
+ }
1091
+ };
1092
+
1093
+ function prefixStyle (style) {
1094
+ if ( vendor === '' ) return style;
1095
+
1096
+ style = style.charAt(0).toUpperCase() + style.substr(1);
1097
+ return vendor + style;
1098
+ }
1099
+
1100
+ dummyStyle = null; // for the sake of it
1101
+
1102
+ if (typeof exports !== 'undefined') exports.iScroll = iScroll;
1103
+ else window.iScroll = iScroll;
1104
+
1105
+ })(window, document);