coolstrap-generator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/.DS_Store +0 -0
  2. data/.gitignore +4 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/Rakefile +6 -0
  6. data/bin/coolstrap +5 -0
  7. data/coolstrap-generator.gemspec +42 -0
  8. data/lib/.DS_Store +0 -0
  9. data/lib/coolstrap-generator.rb +39 -0
  10. data/lib/coolstrap-generator/.DS_Store +0 -0
  11. data/lib/coolstrap-generator/builder/middleman.rb +0 -0
  12. data/lib/coolstrap-generator/cli.rb +71 -0
  13. data/lib/coolstrap-generator/generate/project.rb +96 -0
  14. data/lib/coolstrap-generator/generate/view.rb +54 -0
  15. data/lib/coolstrap-generator/logger.rb +13 -0
  16. data/lib/coolstrap-generator/middleman/helpers.rb +176 -0
  17. data/lib/coolstrap-generator/templates/.DS_Store +0 -0
  18. data/lib/coolstrap-generator/templates/app/.DS_Store +0 -0
  19. data/lib/coolstrap-generator/templates/app/assets/.DS_Store +0 -0
  20. data/lib/coolstrap-generator/templates/app/assets/fonts/fontawesome-webfont.eot +0 -0
  21. data/lib/coolstrap-generator/templates/app/assets/fonts/fontawesome-webfont.svg +255 -0
  22. data/lib/coolstrap-generator/templates/app/assets/fonts/fontawesome-webfont.ttf +0 -0
  23. data/lib/coolstrap-generator/templates/app/assets/fonts/fontawesome-webfont.woff +0 -0
  24. data/lib/coolstrap-generator/templates/app/assets/images/.DS_Store +0 -0
  25. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/arrow-list.png +0 -0
  26. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/arrow.png +0 -0
  27. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/menu.png +0 -0
  28. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/startup/smatphone.png +0 -0
  29. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/startup/smatphone@2x.png +0 -0
  30. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/startup/tablet-landscape.png +0 -0
  31. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/startup/tablet-landscape@2x.png +0 -0
  32. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/startup/tablet-portrait.png +0 -0
  33. data/lib/coolstrap-generator/templates/app/assets/images/coolstrap/startup/tablet-portrait@2x.png +0 -0
  34. data/lib/coolstrap-generator/templates/app/assets/images/startup/smatphone.png +0 -0
  35. data/lib/coolstrap-generator/templates/app/assets/images/startup/smatphone@2x.png +0 -0
  36. data/lib/coolstrap-generator/templates/app/assets/images/startup/tablet-landscape.png +0 -0
  37. data/lib/coolstrap-generator/templates/app/assets/images/startup/tablet-landscape@2x.png +0 -0
  38. data/lib/coolstrap-generator/templates/app/assets/images/startup/tablet-portrait.png +0 -0
  39. data/lib/coolstrap-generator/templates/app/assets/images/startup/tablet-portrait@2x.png +0 -0
  40. data/lib/coolstrap-generator/templates/app/assets/javascripts/.DS_Store +0 -0
  41. data/lib/coolstrap-generator/templates/app/assets/javascripts/app.js +18 -0
  42. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/_Coolstrap.App.coffee +39 -0
  43. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/_Coolstrap.Console.coffee +49 -0
  44. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/_Coolstrap.Constants.coffee +89 -0
  45. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/_Coolstrap.js +13 -0
  46. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/build/_wrap-start.js +18 -0
  47. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/coolstrap-0.1.js +20 -0
  48. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/coolstrap-0.1.packed.js +23 -0
  49. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/fallback/_Coolstrap.Fallback.Android.coffee +53 -0
  50. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/fallback/_Coolstrap.Fallback.iOS.coffee +29 -0
  51. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/framework/_Coolstrap.Framework.Articles.coffee +34 -0
  52. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/framework/_Coolstrap.Framework.Dialogs.coffee +33 -0
  53. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/framework/_Coolstrap.Framework.Navigation.coffee +118 -0
  54. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/framework/_Coolstrap.Framework.Sections.coffee +60 -0
  55. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/lib/iscroll.js +1076 -0
  56. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/lib/modernizr-2.5.3.js +1265 -0
  57. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/lib/zepto-1.0rc1.js +1357 -0
  58. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/navigate/_Coolstrap.Navigate.History.coffee +164 -0
  59. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/navigate/_Coolstrap.Navigate.coffee +105 -0
  60. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/plugins/_Coolstrap.Plugins.coffee +157 -0
  61. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/util/_Coolstrap.Util.Core.coffee +54 -0
  62. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/util/_Coolstrap.Util.Platform.coffee +89 -0
  63. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/util/_Coolstrap.Util.UI.coffee +96 -0
  64. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/util/_Coolstrap.Util.coffee +41 -0
  65. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/view/_Coolstrap.View.Article.coffee +43 -0
  66. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/view/_Coolstrap.View.Aside.coffee +65 -0
  67. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/view/_Coolstrap.View.Dialog.coffee +129 -0
  68. data/lib/coolstrap-generator/templates/app/assets/javascripts/coolstrap/view/_Coolstrap.View.Scroll.coffee +191 -0
  69. data/lib/coolstrap-generator/templates/app/assets/stylesheets/.DS_Store +0 -0
  70. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/_structure.scss +8 -0
  71. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/coolstrap.css.scss +2 -0
  72. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/_components.scss +5 -0
  73. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/_layout.scss +4 -0
  74. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/_utilities.scss +6 -0
  75. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/components/_dialog.scss +122 -0
  76. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/components/_formelements.scss +89 -0
  77. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/components/_listview.scss +76 -0
  78. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/components/_navigations.scss +192 -0
  79. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/components/_tools.scss +169 -0
  80. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/layout/_layers.scss +57 -0
  81. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/layout/_layout.scss +62 -0
  82. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/layout/_positions.scss +38 -0
  83. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/layout/_transitions.scss +35 -0
  84. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/utilities/_animate.scss +63 -0
  85. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/utilities/_helpers.scss +82 -0
  86. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/utilities/_icons.scss +336 -0
  87. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/utilities/_mixins.scss +45 -0
  88. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/utilities/_reset.scss +367 -0
  89. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/structure/utilities/_variables.scss +176 -0
  90. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/themes/_default.scss +255 -0
  91. data/lib/coolstrap-generator/templates/app/assets/stylesheets/coolstrap/themes/coolstrap.css.scss +164 -0
  92. data/lib/coolstrap-generator/templates/app/assets/stylesheets/customtheme.css.scss +19 -0
  93. data/lib/coolstrap-generator/templates/app/components/_formelements.html.haml +130 -0
  94. data/lib/coolstrap-generator/templates/app/components/_tabbar.html.haml +343 -0
  95. data/lib/coolstrap-generator/templates/app/components/_toolbar.html.haml +463 -0
  96. data/lib/coolstrap-generator/templates/app/components/formelements.html.haml +196 -0
  97. data/lib/coolstrap-generator/templates/app/components/listview/_complexlistavatar.html.haml.erb +77 -0
  98. data/lib/coolstrap-generator/templates/app/components/listview/_simplelist.html.haml.erb +31 -0
  99. data/lib/coolstrap-generator/templates/app/components/tabbar.html.haml.erb +16 -0
  100. data/lib/coolstrap-generator/templates/app/components/toolbar.html.haml.erb +32 -0
  101. data/lib/coolstrap-generator/templates/app/index.html.haml.erb +21 -0
  102. data/lib/coolstrap-generator/templates/app/layout.haml.erb +79 -0
  103. data/lib/coolstrap-generator/templates/app/views/.DS_Store +0 -0
  104. data/lib/coolstrap-generator/templates/app/views/_home.haml.erb +31 -0
  105. data/lib/coolstrap-generator/templates/app/views/shared/_aside_onbottom.haml +2 -0
  106. data/lib/coolstrap-generator/templates/app/views/shared/_aside_onleft.haml +56 -0
  107. data/lib/coolstrap-generator/templates/app/views/shared/_aside_onright.haml +66 -0
  108. data/lib/coolstrap-generator/templates/app/views/shared/_aside_ontop.haml +19 -0
  109. data/lib/coolstrap-generator/templates/defaults/Gemfile.erb +3 -0
  110. data/lib/coolstrap-generator/templates/defaults/LICENSE.erb +1 -0
  111. data/lib/coolstrap-generator/templates/defaults/Readme.mkd.erb +1 -0
  112. data/lib/coolstrap-generator/templates/defaults/config.erb +42 -0
  113. data/lib/coolstrap-generator/templates/defaults/gitignore.erb +2 -0
  114. data/lib/coolstrap-generator/templates/rakefile +102 -0
  115. data/lib/coolstrap-generator/templates/specs/app_spec.coffee +3 -0
  116. data/lib/coolstrap-generator/utils.rb +82 -0
  117. data/lib/coolstrap-generator/version.rb +5 -0
  118. data/readme.md +107 -0
  119. data/spec/cli/command_spec.rb +88 -0
  120. data/spec/coolstrap-generator/generate/project_spec.rb +126 -0
  121. data/spec/coolstrap-generator/generate/view_spec.rb +26 -0
  122. data/spec/coolstrap-generator/logger_spec.rb +25 -0
  123. data/spec/coolstrap-generator/middleman/helpers_spec.rb +16 -0
  124. data/spec/coolstrap-generator/utils_spec.rb +120 -0
  125. data/spec/spec_helper.rb +39 -0
  126. metadata +321 -0
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Coolstrapp.js
3
+ */
4
+ var COOLSTRAP = COOLSTRAP || {};
5
+ COOLSTRAP.VERSION = '0.9';
6
+
7
+ COOLSTRAP.Attributes || (COOLSTRAP.Attributes = {});
8
+ COOLSTRAP.Data || (COOLSTRAP.Data = {});
9
+ COOLSTRAP.View || (COOLSTRAP.View = {});
10
+ COOLSTRAP.Device || (COOLSTRAP.Device = {});
11
+ COOLSTRAP.Fallback || (COOLSTRAP.Fallback = {});
12
+ COOLSTRAP.Framework || (COOLSTRAP.Framework = {});
13
+ COOLSTRAP.dom = "undefined" !== typeof window ? window.jQuery || window.Zepto || null : null;
@@ -0,0 +1,18 @@
1
+ //////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // Copyright 2012 Rhyboo (http://needmorecaffeine.com | @needmorecaffeine)
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ //
17
+ //////////////////////////////////////////////////////////////////////////////////////
18
+
@@ -0,0 +1,20 @@
1
+ //= require "coolstrap/_Coolstrap"
2
+ //= require "coolstrap/_Coolstrap.App"
3
+ //= require "coolstrap/_Coolstrap.Console"
4
+ //= require "coolstrap/_Coolstrap.Constants"
5
+ //= require "coolstrap/plugins/_Coolstrap.Plugins"
6
+ //= require "coolstrap/util/_Coolstrap.Util"
7
+ //= require "coolstrap/util/_Coolstrap.Util.Core"
8
+ //= require "coolstrap/util/_Coolstrap.Util.Platform"
9
+ //= require "coolstrap/util/_Coolstrap.Util.UI"
10
+ //= require "coolstrap/framework/_Coolstrap.Framework.Sections"
11
+ //= require "coolstrap/framework/_Coolstrap.Framework.Articles"
12
+ //= require "coolstrap/framework/_Coolstrap.Framework.Navigation"
13
+ //= require "coolstrap/navigate/_Coolstrap.Navigate"
14
+ //= require "coolstrap/navigate/_Coolstrap.Navigate.History"
15
+ //= require "coolstrap/view/_Coolstrap.View.Article"
16
+ //= require "coolstrap/view/_Coolstrap.View.Aside"
17
+ //= require "coolstrap/view/_Coolstrap.View.Scroll"
18
+ //= require "coolstrap/view/_Coolstrap.View.Dialog"
19
+ //= require "coolstrap/fallback/_Coolstrap.Fallback.Android"
20
+ //= require "coolstrap/fallback/_Coolstrap.Fallback.iOS"
@@ -0,0 +1,23 @@
1
+ //= require "build/_wrap-start"
2
+ //= require "lib/zepto-1.0rc1"
3
+ //= require "lib/iscroll"
4
+ //= require "_Coolstrap"
5
+ //= require "_Coolstrap.App"
6
+ //= require "_Coolstrap.Console"
7
+ //= require "_Coolstrap.Constants"
8
+ //= require "plugins/_Coolstrap.Plugins"
9
+ //= require "util/_Coolstrap.Util"
10
+ //= require "util/_Coolstrap.Util.Core"
11
+ //= require "util/_Coolstrap.Util.Platform"
12
+ //= require "util/_Coolstrap.Util.UI"
13
+ //= require "framework/_Coolstrap.Framework.Sections"
14
+ //= require "framework/_Coolstrap.Framework.Articles"
15
+ //= require "framework/_Coolstrap.Framework.Navigation"
16
+ //= require "navigate/_Coolstrap.Navigate"
17
+ //= require "navigate/_Coolstrap.Navigate.History"
18
+ //= require "view/_Coolstrap.View.Article"
19
+ //= require "view/_Coolstrap.View.Aside"
20
+ //= require "view/_Coolstrap.View.Scroll"
21
+ //= require "view/_Coolstrap.View.Dialog"
22
+ //= require "fallback/_Coolstrap.Fallback.Android"
23
+ //= require "fallback/_Coolstrap.Fallback.iOS"
@@ -0,0 +1,53 @@
1
+ ###
2
+ # Fallback to Android unexpected behaviors.
3
+ # Android Sucks!
4
+ #
5
+ # @namespace COOLSTRAP.Fallback
6
+ # @class Android
7
+ #
8
+ # @author Abraham Barrera <abarrerac@gmail.com> || @abraham_barrera
9
+ ###
10
+
11
+ COOLSTRAP.Fallback.Android = ((cool) ->
12
+ CLASS = cool.Constants.CLASS
13
+ _enableElement = (element) ->
14
+ element.removeAttr "disabled"
15
+
16
+ _disableElement = (element) ->
17
+ element.attr "disabled", "disabled"
18
+
19
+ _addClassActive = (element) ->
20
+ cool.dom(this).addClass CLASS.ACTIVE
21
+
22
+ _removeClassActive = (element) ->
23
+ cool.dom(this).removeClass CLASS.ACTIVE
24
+
25
+ ###
26
+ # add active class to buttons when pressed
27
+ # @method buttons
28
+ ###
29
+ buttons = ->
30
+ environment = cool.Util.Platform.environment()
31
+ if environment.isMobile
32
+ cool.dom(document.body).on "touchstart", "a", _addClassActive
33
+ cool.dom(document.body).on "touchend", "a", _removeClassActive
34
+
35
+ ###
36
+ # disable input elements
37
+ # @method inputs
38
+ ###
39
+ inputs = (article_id, active) ->
40
+ environment = cool.Util.Platform.environment()
41
+ if environment.isMobile and environment.os.name is "android" and environment.os.version < "4"
42
+ selector = article_id + " input, " + article_id + " textarea, " + article_id + " select"
43
+ input_elements = cool.dom(selector)
44
+ i = 0
45
+ len = input_elements.length
46
+
47
+ while i < len
48
+ (if (active) then _enableElement(input_elements[i]) else _disableElement(input_elements[i]))
49
+ i++
50
+
51
+ buttons: buttons
52
+ inputs: inputs
53
+ )(COOLSTRAP)
@@ -0,0 +1,29 @@
1
+ ###
2
+ # Fallback to iOS unexpected behaviors.
3
+ #
4
+ # @namespace COOLSTRAP.Fallback
5
+ # @class iOS
6
+ #
7
+ # @author Abraham Barrera <abarrerac@gmail.com> || @abraham_barrera
8
+ ###
9
+
10
+ COOLSTRAP.Fallback.iOS = ((cool, document) ->
11
+ VIEWPORT_META = document.querySelector and document.querySelector("meta[name=\"viewport\"]")
12
+
13
+ ###
14
+ # fix for iPhone viewport scale bug
15
+ # http://www.blog.highub.com/mobile-2/a-fix-for-iphone-viewport-scale-bug/
16
+ #
17
+ # @method scaleFix
18
+ ###
19
+ scaleFix = ->
20
+ env = cool.Util.Platform.environment()
21
+ _gestureStart = ->
22
+ VIEWPORT_META.content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6"
23
+
24
+ if VIEWPORT_META and (env.isMobile and env.os.name is "ios")
25
+ VIEWPORT_META.content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0"
26
+ document.addEventListener "gesturestart", _gestureStart, false
27
+
28
+ scaleFix: scaleFix
29
+ )(COOLSTRAP, document)
@@ -0,0 +1,34 @@
1
+ ###
2
+ * Initialize all <article> element in sections
3
+ *
4
+ * @namespace COOLSTRAP.Framework
5
+ * @class Articles
6
+ *
7
+ * @author Abraham Barrera <abarrerac@gmail.com> || @abraham_barrera
8
+ ###
9
+
10
+ COOLSTRAP.Framework.Articles = ((cool) ->
11
+ SCROLLABLE_CLASS = cool.Constants.CLASS.SCROLLABLE
12
+ _initElement = (selector, callback) ->
13
+ found_elements = cool.dom(selector)
14
+ i = 0
15
+ len = found_elements.length
16
+
17
+ while i < len
18
+ element = cool.dom(found_elements[i])
19
+ cool.Util.Core.execute callback, element
20
+ i++
21
+
22
+ _initScroller = (element) ->
23
+ cool.View.Scroll.init element
24
+
25
+ ###
26
+ * Setup the elements of an article
27
+ *
28
+ * @method setup
29
+ ###
30
+ setup = ->
31
+ _initElement "." + SCROLLABLE_CLASS, _initScroller
32
+
33
+ setup: setup
34
+ )(COOLSTRAP)
@@ -0,0 +1,33 @@
1
+ ###
2
+ * Initialize all div[role=dialog] element
3
+ *
4
+ * @namespace COOLSTRAP.Framework
5
+ * @class Dialogs
6
+ *
7
+ * @author Abraham Barrera <abarrerac@gmail.com> || @abraham_barrera
8
+ ###
9
+
10
+ COOLSTRAP.Framework.Dialogs = ((cool) ->
11
+ ELEMENT = COOLSTRAP.Constants.ELEMENT
12
+ _initElement = (selector, callback) ->
13
+ found_elements = cool.dom(selector)
14
+ i = undefined
15
+ i = 0
16
+ len = found_elements.length
17
+
18
+ while i < len
19
+ element = cool.dom(found_elements[i])
20
+ cool.Util.Core.execute callback, element
21
+ i++
22
+
23
+ _initDialog = (element) ->
24
+ ###
25
+ * Setup all dialog elements
26
+ *
27
+ * @method setup
28
+ ###
29
+ setup = ->
30
+ _initElement ELEMENT.DIALOG, _initDialog
31
+
32
+ setup: setup
33
+ )(COOLSTRAP)
@@ -0,0 +1,118 @@
1
+ ###
2
+ * Initialize the events for manage navigation
3
+ *
4
+ * @namespace COOLSTRAP.Framework
5
+ * @class Navigation
6
+ *
7
+ * @author Abraham Barrera <abarrerac@gmail.com> || @abraham_barrera
8
+ ###
9
+
10
+ COOLSTRAP.Framework.Navigation = ((cool, window) ->
11
+ ATTRIBUTE = cool.Constants.ATTRIBUTE
12
+ CLASS = cool.Constants.CLASS
13
+ ELEMENT = cool.Constants.ELEMENT
14
+ TARGET = cool.Constants.TARGET
15
+ TRANSITION = cool.Constants.TRANSITION
16
+ COMMAND = cool.Constants.COMMAND
17
+ SELECTORS =
18
+ HREF_TARGET: "[role=\"main\"] a[href][data-target]"
19
+ HREF_TARGET_FROM_ASIDE: "aside a[href][data-target]"
20
+
21
+ console = cool.Console
22
+ _goSection = (section_id) ->
23
+ section_id = cool.Util.parseUrl(section_id)
24
+ cool.Navigate.section section_id
25
+
26
+ _goArticle = (element) ->
27
+ section_id = cool.Navigate.History.current()
28
+ article_id = element.attr(ATTRIBUTE.HREF)
29
+ cool.Navigate.article section_id, article_id
30
+
31
+ _goDialog = (element, close) ->
32
+ dialog_id = element.attr(ATTRIBUTE.HREF)
33
+ cool.Navigate.dialog dialog_id, close or source_element: element
34
+
35
+ _hideAsideIfNecesary = (aside_id, link) ->
36
+ target_id = link.attr(ATTRIBUTE.HREF)
37
+ parent = cool.dom(target_id).parents(ELEMENT.ASIDE).first()
38
+ return false if target_id is aside_id
39
+ if not parent or ("#" + parent.attr(ATTRIBUTE.ID) isnt aside_id and target_id isnt "#" + TARGET.BACK)
40
+ cool.View.Aside.hide aside_id
41
+ true
42
+
43
+ _goAside = (element) ->
44
+ aside_id = element.attr(ATTRIBUTE.HREF)
45
+ current_aside = cool.dom(ELEMENT.ASIDE + "." + CLASS.CURRENT).first()
46
+ hide_aside = false
47
+ hide_aside = _hideAsideIfNecesary("#" + current_aside.attr(ATTRIBUTE.ID), element) if current_aside
48
+ if hide_aside
49
+ setTimeout (->
50
+ cool.Navigate.aside aside_id
51
+ ), TRANSITION.DURATION
52
+ else
53
+ cool.Navigate.aside aside_id
54
+
55
+ _goBack = (container_id) ->
56
+ cool.Navigate.back container_id
57
+
58
+ _selectTarget = (link) ->
59
+ target_type = link.data(ATTRIBUTE.TARGET)
60
+ link_container = link.parents(ELEMENT.ASIDE).attr(ATTRIBUTE.ID)
61
+ switch target_type
62
+ when TARGET.SECTION
63
+ target_id = link.attr(ATTRIBUTE.HREF)
64
+ _goSection target_id, link_container
65
+ when TARGET.ARTICLE
66
+ _goArticle link
67
+ when TARGET.ASIDE
68
+ _goAside link
69
+ when TARGET.DIALOG
70
+ _goDialog link
71
+ when TARGET.BACK
72
+ _goBack link_container
73
+ when TARGET.CLOSE
74
+ _goDialog link, COMMAND.CLOSE_DIALOG
75
+
76
+ _loadTargetFromAside = (event) ->
77
+ link = cool.dom(this)
78
+ aside_id = "#" + link.parents(ELEMENT.ASIDE).attr(ATTRIBUTE.ID)
79
+ target_type = link.data(ATTRIBUTE.TARGET)
80
+ if target_type is TARGET.BACK or target_type is TARGET.CLOSE
81
+ _selectTarget link
82
+ else
83
+ if target_type is TARGET.ARTICLE
84
+ cool.dom(ELEMENT.ASIDE + aside_id + " " + SELECTORS.HREF_TARGET).removeClass CLASS.CURRENT
85
+ link.addClass CLASS.CURRENT
86
+ if _hideAsideIfNecesary(aside_id, link)
87
+ setTimeout (->
88
+ _selectTarget link
89
+ ), TRANSITION.DURATION
90
+ else
91
+ _selectTarget link
92
+ event.preventDefault()
93
+
94
+ _loadTarget = (event) ->
95
+ link = cool.dom(this)
96
+ _selectTarget link
97
+ event.preventDefault()
98
+
99
+
100
+ ###
101
+ * Initializes the automatic subscription events by markup of the project.
102
+ *
103
+ * @method setup
104
+ *
105
+ ###
106
+
107
+ setup = ->
108
+ if typeof document.documentElement.ontouchstart isnt "undefined"
109
+ cool.dom(SELECTORS.HREF_TARGET_FROM_ASIDE).tap _loadTargetFromAside
110
+ cool.dom(SELECTORS.HREF_TARGET).tap _loadTarget
111
+ else
112
+ cool.dom(SELECTORS.HREF_TARGET_FROM_ASIDE).click _loadTargetFromAside
113
+ cool.dom(SELECTORS.HREF_TARGET).click _loadTarget
114
+ cool.Fallback.Android.buttons()
115
+ cool.Navigate.History.setup()
116
+
117
+ setup: setup
118
+ )(COOLSTRAP, window)
@@ -0,0 +1,60 @@
1
+ ###
2
+ * Initialize all <section> elements
3
+ *
4
+ * @namespace COOLSTRAP.Framework
5
+ * @class Sections
6
+ *
7
+ * @author Abraham Barrera <abarrerac@gmail.com> || @abraham_barrera
8
+ ###
9
+
10
+ COOLSTRAP.Framework.Sections = ((cool) ->
11
+ ELEMENT = cool.Constants.ELEMENT
12
+ CLASS = cool.Constants.CLASS
13
+ ATTRIBUTE = cool.Constants.ATTRIBUTE
14
+ _initFirstSection = (sections) ->
15
+ first_section = sections.first()
16
+ first_section_id = "#" + first_section.attr(ATTRIBUTE.ID)
17
+ first_section.addClass CLASS.CURRENT
18
+ cool.Navigate.History.add
19
+ section_id: first_section_id
20
+ replace_state: true
21
+
22
+ _initAllSections = (sections) ->
23
+ i = 0
24
+ len = sections.length
25
+
26
+ while i < len
27
+ section = cool.dom(sections[i])
28
+ _initArticles section
29
+ i++
30
+
31
+ _initArticles = (section) ->
32
+ first_article = section.children(ELEMENT.ARTICLE).first()
33
+ first_article.addClass CLASS.CURRENT
34
+ first_article_id = first_article.attr(ATTRIBUTE.ID)
35
+ section_id = "#" + section.attr(ATTRIBUTE.ID)
36
+
37
+ _initAsideArticles = (asides) ->
38
+ i = 0
39
+ len = asides.length
40
+
41
+ while i < len
42
+ aside = cool.dom(asides[i])
43
+ _initArticles aside
44
+ i++
45
+
46
+ ###
47
+ * Initializes all <section> element of the application
48
+ *
49
+ * @method setup
50
+ ###
51
+
52
+ setup = ->
53
+ sections = cool.dom(ELEMENT.SECTION)
54
+ asides = cool.dom(ELEMENT.ASIDE)
55
+ _initFirstSection sections
56
+ _initAllSections sections
57
+ _initAsideArticles asides
58
+
59
+ setup: setup
60
+ )(COOLSTRAP)
@@ -0,0 +1,1076 @@
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 capabilities
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
+ }
958
+ },
959
+
960
+ scrollTo: function (x, y, time, relative) {
961
+ var that = this,
962
+ step = x,
963
+ i, l;
964
+
965
+ that.stop();
966
+
967
+ if (!step.length) step = [{ x: x, y: y, time: time, relative: relative }];
968
+
969
+ for (i=0, l=step.length; i<l; i++) {
970
+ if (step[i].relative) { step[i].x = that.x - step[i].x; step[i].y = that.y - step[i].y; }
971
+ that.steps.push({ x: step[i].x, y: step[i].y, time: step[i].time || 0 });
972
+ }
973
+
974
+ that._startAni();
975
+ },
976
+
977
+ scrollToElement: function (el, time) {
978
+ var that = this, pos;
979
+ el = el.nodeType ? el : that.scroller.querySelector(el);
980
+ if (!el) return;
981
+
982
+ pos = that._offset(el);
983
+ pos.left += that.wrapperOffsetLeft;
984
+ pos.top += that.wrapperOffsetTop;
985
+
986
+ pos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;
987
+ pos.top = pos.top > that.minScrollY ? that.minScrollY : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;
988
+ time = time === undefined ? m.max(m.abs(pos.left)*2, m.abs(pos.top)*2) : time;
989
+
990
+ that.scrollTo(pos.left, pos.top, time);
991
+ },
992
+
993
+ scrollToPage: function (pageX, pageY, time) {
994
+ var that = this, x, y;
995
+
996
+ time = time === undefined ? 400 : time;
997
+
998
+ if (that.options.onScrollStart) that.options.onScrollStart.call(that);
999
+
1000
+ if (that.options.snap) {
1001
+ pageX = pageX == 'next' ? that.currPageX+1 : pageX == 'prev' ? that.currPageX-1 : pageX;
1002
+ pageY = pageY == 'next' ? that.currPageY+1 : pageY == 'prev' ? that.currPageY-1 : pageY;
1003
+
1004
+ pageX = pageX < 0 ? 0 : pageX > that.pagesX.length-1 ? that.pagesX.length-1 : pageX;
1005
+ pageY = pageY < 0 ? 0 : pageY > that.pagesY.length-1 ? that.pagesY.length-1 : pageY;
1006
+
1007
+ that.currPageX = pageX;
1008
+ that.currPageY = pageY;
1009
+ x = that.pagesX[pageX];
1010
+ y = that.pagesY[pageY];
1011
+ } else {
1012
+ x = -that.wrapperW * pageX;
1013
+ y = -that.wrapperH * pageY;
1014
+ if (x < that.maxScrollX) x = that.maxScrollX;
1015
+ if (y < that.maxScrollY) y = that.maxScrollY;
1016
+ }
1017
+
1018
+ that.scrollTo(x, y, time);
1019
+ },
1020
+
1021
+ disable: function () {
1022
+ this.stop();
1023
+ this._resetPos(0);
1024
+ this.enabled = false;
1025
+
1026
+ // If disabled after touchstart we make sure that there are no left over events
1027
+ this._unbind(MOVE_EV);
1028
+ this._unbind(END_EV);
1029
+ this._unbind(CANCEL_EV);
1030
+ },
1031
+
1032
+ enable: function () {
1033
+ this.enabled = true;
1034
+ },
1035
+
1036
+ stop: function () {
1037
+ if (this.options.useTransition) this._unbind('webkitTransitionEnd');
1038
+ else cancelFrame(this.aniTime);
1039
+ this.steps = [];
1040
+ this.moved = false;
1041
+ this.animating = false;
1042
+ },
1043
+
1044
+ zoom: function (x, y, scale, time) {
1045
+ var that = this,
1046
+ relScale = scale / that.scale;
1047
+
1048
+ if (!that.options.useTransform) return;
1049
+
1050
+ that.zoomed = true;
1051
+ time = time === undefined ? 200 : time;
1052
+ x = x - that.wrapperOffsetLeft - that.x;
1053
+ y = y - that.wrapperOffsetTop - that.y;
1054
+ that.x = x - x * relScale + that.x;
1055
+ that.y = y - y * relScale + that.y;
1056
+
1057
+ that.scale = scale;
1058
+ that.refresh();
1059
+
1060
+ that.x = that.x > 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x;
1061
+ that.y = that.y > that.minScrollY ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;
1062
+
1063
+ that.scroller.style[vendor + 'TransitionDuration'] = time + 'ms';
1064
+ that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose + ' scale(' + scale + ')';
1065
+ that.zoomed = false;
1066
+ },
1067
+
1068
+ isReady: function () {
1069
+ return !this.moved && !this.zoomed && !this.animating;
1070
+ }
1071
+ };
1072
+
1073
+ if (typeof exports !== 'undefined') exports.iScroll = iScroll;
1074
+ else window.iScroll = iScroll;
1075
+
1076
+ })();