upjs-rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (409) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gemfile +8 -0
  4. data/Gemfile.lock +42 -0
  5. data/{LICENSE.txt → LICENSE} +1 -1
  6. data/Rakefile +38 -0
  7. data/dist/up.css +70 -0
  8. data/dist/up.js +2552 -0
  9. data/dist/up.min.css +1 -0
  10. data/dist/up.min.js +1 -0
  11. data/doc/theme/Gruntfile.js +25 -0
  12. data/doc/theme/README.md +29 -0
  13. data/doc/theme/api/.keep +0 -0
  14. data/doc/theme/assets/css/external-small.png +0 -0
  15. data/doc/theme/assets/css/logo.png +0 -0
  16. data/doc/theme/assets/css/main.css +859 -0
  17. data/doc/theme/assets/css/main.less +897 -0
  18. data/doc/theme/assets/favicon.png +0 -0
  19. data/doc/theme/assets/img/bgscreen.png +0 -0
  20. data/doc/theme/assets/img/spinner.gif +0 -0
  21. data/doc/theme/assets/index.html +10 -0
  22. data/doc/theme/assets/js/api-filter.js +52 -0
  23. data/doc/theme/assets/js/api-list.js +251 -0
  24. data/doc/theme/assets/js/api-search.js +98 -0
  25. data/doc/theme/assets/js/apidocs.js +369 -0
  26. data/doc/theme/assets/js/yui-prettify.js +17 -0
  27. data/doc/theme/assets/vendor/prettify/CHANGES.html +130 -0
  28. data/doc/theme/assets/vendor/prettify/COPYING +202 -0
  29. data/doc/theme/assets/vendor/prettify/README.html +203 -0
  30. data/doc/theme/assets/vendor/prettify/prettify-min.css +1 -0
  31. data/doc/theme/assets/vendor/prettify/prettify-min.js +1 -0
  32. data/doc/theme/layouts/main.handlebars +54 -0
  33. data/doc/theme/layouts/xhr.handlebars +7 -0
  34. data/doc/theme/package.json +53 -0
  35. data/doc/theme/partials/attrs.handlebars +141 -0
  36. data/doc/theme/partials/classes.handlebars +210 -0
  37. data/doc/theme/partials/events.handlebars +145 -0
  38. data/doc/theme/partials/exampleurl.handlebars +8 -0
  39. data/doc/theme/partials/files.handlebars +7 -0
  40. data/doc/theme/partials/index.handlebars +18 -0
  41. data/doc/theme/partials/method.handlebars +201 -0
  42. data/doc/theme/partials/module.handlebars +92 -0
  43. data/doc/theme/partials/options.handlebars +23 -0
  44. data/doc/theme/partials/props.handlebars +128 -0
  45. data/doc/theme/partials/sidebar.handlebars +27 -0
  46. data/doc/theme/theme.json +4 -0
  47. data/doc/yuidoc-helpers.js +0 -0
  48. data/doc/yuidoc.json +15 -0
  49. data/lib/assets/javascripts/up/browser.js.coffee +11 -0
  50. data/lib/assets/javascripts/up/bus.js.coffee +37 -9
  51. data/lib/assets/javascripts/up/flow.js.coffee +131 -58
  52. data/lib/assets/javascripts/up/form.js.coffee +70 -35
  53. data/lib/assets/javascripts/up/history.js.coffee +31 -9
  54. data/lib/assets/javascripts/up/link.js.coffee +122 -27
  55. data/lib/assets/javascripts/up/magic.js.coffee +87 -21
  56. data/lib/assets/javascripts/up/marker.js.coffee +37 -0
  57. data/lib/assets/javascripts/up/modal.js.coffee +183 -42
  58. data/lib/assets/javascripts/up/motion.js.coffee +65 -43
  59. data/lib/assets/javascripts/up/navigation.js.coffee +29 -11
  60. data/lib/assets/javascripts/up/popup.js.coffee +104 -29
  61. data/lib/assets/javascripts/up/tooltip.js.coffee +93 -0
  62. data/lib/assets/javascripts/up/util.js.coffee +139 -14
  63. data/lib/assets/javascripts/up.js.coffee +19 -0
  64. data/lib/assets/stylesheets/up/close.css.sass +2 -0
  65. data/lib/assets/stylesheets/up/modal.css.sass +23 -26
  66. data/lib/assets/stylesheets/up/popup.css.sass +4 -0
  67. data/lib/assets/stylesheets/up/tooltip.css.sass +17 -0
  68. data/lib/assets/stylesheets/{up/index.css → up.css} +0 -0
  69. data/lib/upjs/rails/version.rb +1 -1
  70. data/spec_app/Bowerfile +3 -0
  71. data/spec_app/Gemfile +6 -0
  72. data/spec_app/Gemfile.lock +11 -1
  73. data/spec_app/app/assets/javascripts/application.js +3 -0
  74. data/spec_app/config/initializers/bower_rails.rb +16 -0
  75. data/spec_app/config/routes.rb +1 -0
  76. data/spec_app/spec/javascripts/helpers/index.js.coffee +1 -0
  77. data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +7 -0
  78. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +4 -0
  79. data/spec_app/spec/javascripts/support/jasmine.yml +50 -0
  80. data/spec_app/spec/javascripts/up/flow_spec.js.coffee +75 -0
  81. data/spec_app/spec/javascripts/up/marker_spec.js.coffee +14 -0
  82. data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +27 -0
  83. data/spec_app/spec/javascripts/up/util_spec.js.coffee +27 -0
  84. data/spec_app/vendor/assets/.bowerrc +3 -0
  85. data/spec_app/vendor/assets/bower.json +8 -0
  86. data/spec_app/vendor/assets/bower_components/jasmine/.bower.json +14 -0
  87. data/spec_app/vendor/assets/bower_components/jasmine/.gitignore +24 -0
  88. data/spec_app/vendor/assets/bower_components/jasmine/.gitmodules +3 -0
  89. data/spec_app/vendor/assets/bower_components/jasmine/.jshintrc +9 -0
  90. data/spec_app/vendor/assets/bower_components/jasmine/.npmignore +21 -0
  91. data/spec_app/vendor/assets/bower_components/jasmine/.rspec +1 -0
  92. data/spec_app/vendor/assets/bower_components/jasmine/.travis.yml +51 -0
  93. data/spec_app/vendor/assets/bower_components/jasmine/CONTRIBUTING.md +121 -0
  94. data/spec_app/vendor/assets/bower_components/jasmine/GOALS_2.0.md +64 -0
  95. data/spec_app/vendor/assets/bower_components/jasmine/Gemfile +12 -0
  96. data/spec_app/vendor/assets/bower_components/jasmine/Gruntfile.js +53 -0
  97. data/spec_app/vendor/assets/bower_components/jasmine/MANIFEST.in +5 -0
  98. data/spec_app/vendor/assets/bower_components/jasmine/MIT.LICENSE +20 -0
  99. data/spec_app/vendor/assets/bower_components/jasmine/README.md +64 -0
  100. data/spec_app/vendor/assets/bower_components/jasmine/RELEASE.md +63 -0
  101. data/spec_app/vendor/assets/bower_components/jasmine/Rakefile +18 -0
  102. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-1.0.0.zip +0 -0
  103. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-1.1.0.zip +0 -0
  104. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-1.2.0.zip +0 -0
  105. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-1.3.0.zip +0 -0
  106. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-1.3.1.zip +0 -0
  107. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-2.0.0.zip +0 -0
  108. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-2.0.1.zip +0 -0
  109. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-2.0.2.zip +0 -0
  110. data/spec_app/vendor/assets/bower_components/jasmine/dist/jasmine-standalone-2.0.3.zip +0 -0
  111. data/spec_app/vendor/assets/bower_components/jasmine/grunt/config/compass.js +10 -0
  112. data/spec_app/vendor/assets/bower_components/jasmine/grunt/config/compress.js +66 -0
  113. data/spec_app/vendor/assets/bower_components/jasmine/grunt/config/concat.js +61 -0
  114. data/spec_app/vendor/assets/bower_components/jasmine/grunt/config/jshint.js +11 -0
  115. data/spec_app/vendor/assets/bower_components/jasmine/grunt/tasks/build_standalone.js +31 -0
  116. data/spec_app/vendor/assets/bower_components/jasmine/grunt/tasks/version.js +14 -0
  117. data/spec_app/vendor/assets/bower_components/jasmine/grunt/templates/SpecRunner.html.jst +26 -0
  118. data/spec_app/vendor/assets/bower_components/jasmine/grunt/templates/licenseBanner.js.jst +22 -0
  119. data/spec_app/vendor/assets/bower_components/jasmine/grunt/templates/version.rb.jst +9 -0
  120. data/spec_app/vendor/assets/bower_components/jasmine/images/__init__.py +0 -0
  121. data/spec_app/vendor/assets/bower_components/jasmine/images/jasmine-horizontal.png +0 -0
  122. data/spec_app/vendor/assets/bower_components/jasmine/images/jasmine-horizontal.svg +102 -0
  123. data/spec_app/vendor/assets/bower_components/jasmine/images/jasmine_favicon.png +0 -0
  124. data/spec_app/vendor/assets/bower_components/jasmine/jasmine-core.gemspec +23 -0
  125. data/spec_app/vendor/assets/bower_components/jasmine/lib/console/console.js +166 -0
  126. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/__init__.py +1 -0
  127. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/boot/boot.js +120 -0
  128. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/boot/node_boot.js +19 -0
  129. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/boot.js +142 -0
  130. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/core.py +60 -0
  131. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/node_example/spec/PlayerSpec.js +60 -0
  132. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/node_example/spec/SpecHelper.js +15 -0
  133. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/node_example/src/Player.js +24 -0
  134. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/node_example/src/Song.js +9 -0
  135. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/spec/PlayerSpec.js +58 -0
  136. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/spec/SpecHelper.js +15 -0
  137. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/src/Player.js +22 -0
  138. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/src/Song.js +7 -0
  139. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/jasmine-html.js +390 -0
  140. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/jasmine.css +61 -0
  141. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/jasmine.js +2593 -0
  142. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/json2.js +478 -0
  143. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/node_boot.js +41 -0
  144. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/version.rb +9 -0
  145. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core.js +39 -0
  146. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core.rb +53 -0
  147. data/spec_app/vendor/assets/bower_components/jasmine/package.json +23 -0
  148. data/spec_app/vendor/assets/bower_components/jasmine/release_notes/2.0.1.md +70 -0
  149. data/spec_app/vendor/assets/bower_components/jasmine/release_notes/2.0.2.md +25 -0
  150. data/spec_app/vendor/assets/bower_components/jasmine/release_notes/20.md +179 -0
  151. data/spec_app/vendor/assets/bower_components/jasmine/requirements.txt +1 -0
  152. data/spec_app/vendor/assets/bower_components/jasmine/setup.py +47 -0
  153. data/spec_app/vendor/assets/bower_components/jasmine/spec/console/ConsoleReporterSpec.js +239 -0
  154. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/AnySpec.js +46 -0
  155. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/CallTrackerSpec.js +105 -0
  156. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ClockSpec.js +445 -0
  157. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/DelayedFunctionSchedulerSpec.js +246 -0
  158. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/EnvSpec.js +85 -0
  159. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ExceptionFormatterSpec.js +63 -0
  160. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ExceptionsSpec.js +68 -0
  161. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ExpectationResultSpec.js +61 -0
  162. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ExpectationSpec.js +427 -0
  163. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/JsApiReporterSpec.js +214 -0
  164. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/MockDateSpec.js +199 -0
  165. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ObjectContainingSpec.js +70 -0
  166. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/PrettyPrintSpec.js +156 -0
  167. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/QueueRunnerSpec.js +271 -0
  168. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/ReportDispatcherSpec.js +40 -0
  169. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/SpecSpec.js +260 -0
  170. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/SpySpec.js +67 -0
  171. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/SpyStrategySpec.js +111 -0
  172. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/SuiteSpec.js +216 -0
  173. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/TimerSpec.js +31 -0
  174. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/UtilSpec.js +28 -0
  175. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/integration/CustomMatchersSpec.js +149 -0
  176. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/integration/EnvSpec.js +506 -0
  177. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/integration/SpecRunningSpec.js +306 -0
  178. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/matchersUtilSpec.js +239 -0
  179. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeCloseToSpec.js +51 -0
  180. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeDefinedSpec.js +18 -0
  181. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeFalsySpec.js +38 -0
  182. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeGreaterThanSpec.js +20 -0
  183. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeLessThanSpec.js +20 -0
  184. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeNaNSpec.js +37 -0
  185. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeNullSpec.js +17 -0
  186. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeSpec.js +17 -0
  187. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeTruthySpec.js +38 -0
  188. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toBeUndefinedSpec.js +18 -0
  189. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toContainSpec.js +26 -0
  190. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toEqualSpec.js +28 -0
  191. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toHaveBeenCalledSpec.js +47 -0
  192. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toHaveBeenCalledWithSpec.js +66 -0
  193. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toMatchSpec.js +34 -0
  194. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toThrowErrorSpec.js +280 -0
  195. data/spec_app/vendor/assets/bower_components/jasmine/spec/core/matchers/toThrowSpec.js +99 -0
  196. data/spec_app/vendor/assets/bower_components/jasmine/spec/helpers/BrowserFlags.js +23 -0
  197. data/spec_app/vendor/assets/bower_components/jasmine/spec/helpers/defineJasmineUnderTest.js +7 -0
  198. data/spec_app/vendor/assets/bower_components/jasmine/spec/helpers/nodeDefineJasmineUnderTest.js +33 -0
  199. data/spec_app/vendor/assets/bower_components/jasmine/spec/html/HtmlReporterSpec.js +616 -0
  200. data/spec_app/vendor/assets/bower_components/jasmine/spec/html/HtmlSpecFilterSpec.js +18 -0
  201. data/spec_app/vendor/assets/bower_components/jasmine/spec/html/MatchersHtmlSpec.js +37 -0
  202. data/spec_app/vendor/assets/bower_components/jasmine/spec/html/PrettyPrintHtmlSpec.js +15 -0
  203. data/spec_app/vendor/assets/bower_components/jasmine/spec/html/QueryStringSpec.js +43 -0
  204. data/spec_app/vendor/assets/bower_components/jasmine/spec/html/ResultsNodeSpec.js +62 -0
  205. data/spec_app/vendor/assets/bower_components/jasmine/spec/javascripts/support/jasmine_selenium_runner.yml +16 -0
  206. data/spec_app/vendor/assets/bower_components/jasmine/spec/performance/large_object_test.js +36 -0
  207. data/spec_app/vendor/assets/bower_components/jasmine/spec/performance/performance_test.js +10 -0
  208. data/spec_app/vendor/assets/bower_components/jasmine/spec/support/jasmine-performance.json +9 -0
  209. data/spec_app/vendor/assets/bower_components/jasmine/spec/support/jasmine-performance.yml +9 -0
  210. data/spec_app/vendor/assets/bower_components/jasmine/spec/support/jasmine.json +10 -0
  211. data/spec_app/vendor/assets/bower_components/jasmine/spec/support/jasmine.yml +25 -0
  212. data/spec_app/vendor/assets/bower_components/jasmine/src/console/ConsoleReporter.js +131 -0
  213. data/spec_app/vendor/assets/bower_components/jasmine/src/console/requireConsole.js +12 -0
  214. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Any.js +36 -0
  215. data/spec_app/vendor/assets/bower_components/jasmine/src/core/CallTracker.js +50 -0
  216. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Clock.js +113 -0
  217. data/spec_app/vendor/assets/bower_components/jasmine/src/core/DelayedFunctionScheduler.js +145 -0
  218. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Env.js +341 -0
  219. data/spec_app/vendor/assets/bower_components/jasmine/src/core/ExceptionFormatter.js +29 -0
  220. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Expectation.js +107 -0
  221. data/spec_app/vendor/assets/bower_components/jasmine/src/core/ExpectationResult.js +45 -0
  222. data/spec_app/vendor/assets/bower_components/jasmine/src/core/JsApiReporter.js +73 -0
  223. data/spec_app/vendor/assets/bower_components/jasmine/src/core/MockDate.js +81 -0
  224. data/spec_app/vendor/assets/bower_components/jasmine/src/core/ObjectContaining.js +34 -0
  225. data/spec_app/vendor/assets/bower_components/jasmine/src/core/PrettyPrinter.js +137 -0
  226. data/spec_app/vendor/assets/bower_components/jasmine/src/core/QueueRunner.js +92 -0
  227. data/spec_app/vendor/assets/bower_components/jasmine/src/core/ReportDispatcher.js +35 -0
  228. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Spec.js +126 -0
  229. data/spec_app/vendor/assets/bower_components/jasmine/src/core/SpyStrategy.js +51 -0
  230. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Suite.js +92 -0
  231. data/spec_app/vendor/assets/bower_components/jasmine/src/core/Timer.js +22 -0
  232. data/spec_app/vendor/assets/bower_components/jasmine/src/core/base.js +102 -0
  233. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/matchersUtil.js +181 -0
  234. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/requireMatchers.js +29 -0
  235. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBe.js +13 -0
  236. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeCloseTo.js +18 -0
  237. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeDefined.js +13 -0
  238. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeFalsy.js +13 -0
  239. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeGreaterThan.js +15 -0
  240. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeLessThan.js +14 -0
  241. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeNaN.js +22 -0
  242. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeNull.js +14 -0
  243. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeTruthy.js +14 -0
  244. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toBeUndefined.js +14 -0
  245. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toContain.js +16 -0
  246. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toEqual.js +20 -0
  247. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toHaveBeenCalled.js +28 -0
  248. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toHaveBeenCalledWith.js +33 -0
  249. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toMatch.js +16 -0
  250. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toThrow.js +46 -0
  251. data/spec_app/vendor/assets/bower_components/jasmine/src/core/matchers/toThrowError.js +156 -0
  252. data/spec_app/vendor/assets/bower_components/jasmine/src/core/requireCore.js +39 -0
  253. data/spec_app/vendor/assets/bower_components/jasmine/src/core/requireInterface.js +59 -0
  254. data/spec_app/vendor/assets/bower_components/jasmine/src/core/util.js +44 -0
  255. data/spec_app/vendor/assets/bower_components/jasmine/src/html/HtmlReporter.js +280 -0
  256. data/spec_app/vendor/assets/bower_components/jasmine/src/html/HtmlSpecFilter.js +12 -0
  257. data/spec_app/vendor/assets/bower_components/jasmine/src/html/QueryString.js +47 -0
  258. data/spec_app/vendor/assets/bower_components/jasmine/src/html/ResultsNode.js +19 -0
  259. data/spec_app/vendor/assets/bower_components/jasmine/src/html/_HTMLReporter.scss +355 -0
  260. data/spec_app/vendor/assets/bower_components/jasmine/src/html/jasmine.scss +1 -0
  261. data/spec_app/vendor/assets/bower_components/jasmine/src/html/requireHtml.js +6 -0
  262. data/spec_app/vendor/assets/bower_components/jasmine/src/templates/example_project_jasmine_tags.html.erb +3 -0
  263. data/spec_app/vendor/assets/bower_components/jasmine/src/templates/version.js.erb +7 -0
  264. data/spec_app/vendor/assets/bower_components/jasmine/src/templates/version.rb.erb +6 -0
  265. data/spec_app/vendor/assets/bower_components/jasmine/src/version.js +3 -0
  266. data/spec_app/vendor/assets/bower_components/jasmine/travis-core-script.sh +14 -0
  267. data/spec_app/vendor/assets/bower_components/jasmine/travis-docs-script.sh +5 -0
  268. data/spec_app/vendor/assets/bower_components/jasmine/travis-node-script.sh +6 -0
  269. data/spec_app/vendor/assets/bower_components/jasmine-ajax/.bower.json +45 -0
  270. data/spec_app/vendor/assets/bower_components/jasmine-ajax/Gruntfile.js +63 -0
  271. data/spec_app/vendor/assets/bower_components/jasmine-ajax/MIT.LICENSE +20 -0
  272. data/spec_app/vendor/assets/bower_components/jasmine-ajax/README.markdown +216 -0
  273. data/spec_app/vendor/assets/bower_components/jasmine-ajax/bower.json +36 -0
  274. data/spec_app/vendor/assets/bower_components/jasmine-ajax/lib/mock-ajax.js +542 -0
  275. data/spec_app/vendor/assets/bower_components/jasmine-ajax/package.json +21 -0
  276. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/boot.js +11 -0
  277. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/fakeRequest.js +262 -0
  278. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/mockAjax.js +45 -0
  279. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/paramParser.js +56 -0
  280. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/requestStub.js +42 -0
  281. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/requestTracker.js +51 -0
  282. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/requireAjax.js +44 -0
  283. data/spec_app/vendor/assets/bower_components/jasmine-ajax/src/stubTracker.js +24 -0
  284. data/spec_app/vendor/assets/bower_components/jasmine-fixture/.bower.json +27 -0
  285. data/spec_app/vendor/assets/bower_components/jasmine-fixture/.gitignore +8 -0
  286. data/spec_app/vendor/assets/bower_components/jasmine-fixture/.npmignore +8 -0
  287. data/spec_app/vendor/assets/bower_components/jasmine-fixture/LICENSE.txt +24 -0
  288. data/spec_app/vendor/assets/bower_components/jasmine-fixture/README.md +118 -0
  289. data/spec_app/vendor/assets/bower_components/jasmine-fixture/bower.json +17 -0
  290. data/spec_app/vendor/assets/bower_components/jasmine-fixture/dist/jasmine-fixture.js +433 -0
  291. data/spec_app/vendor/assets/bower_components/jasmine-fixture/dist/jasmine-fixture.min.js +5 -0
  292. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/basic-usage-spec.coffee +14 -0
  293. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/helpers/invariants.coffee +17 -0
  294. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/helpers/spec-within-a-spec.coffee +24 -0
  295. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/helpers/tmp-files.coffee +8 -0
  296. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/support/jasmine1-testem-config.json +11 -0
  297. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/support/jasmine2-testem-config.json +11 -0
  298. data/spec_app/vendor/assets/bower_components/jasmine-fixture/vendor/js/jquery-1.11.0.js +10337 -0
  299. data/spec_app/vendor/assets/bower_components/jasmine-fixture/vendor/js/jquery-1.8.3.js +9472 -0
  300. data/spec_app/vendor/assets/bower_components/jasmine-fixture/vendor/js/jquery-2.1.0.js +9111 -0
  301. data/spec_app/vendor/assets/bower_components/jasmine-jquery/.bower.json +26 -0
  302. data/spec_app/vendor/assets/bower_components/jasmine-jquery/CONTRIBUTING.md +28 -0
  303. data/spec_app/vendor/assets/bower_components/jasmine-jquery/Gruntfile.js +33 -0
  304. data/spec_app/vendor/assets/bower_components/jasmine-jquery/MIT.LICENSE +20 -0
  305. data/spec_app/vendor/assets/bower_components/jasmine-jquery/README.md +362 -0
  306. data/spec_app/vendor/assets/bower_components/jasmine-jquery/bower.json +16 -0
  307. data/spec_app/vendor/assets/bower_components/jasmine-jquery/lib/jasmine-jquery.js +813 -0
  308. data/spec_app/vendor/assets/bower_components/jasmine-jquery/package.json +26 -0
  309. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/fixture_with_javascript.html +1 -0
  310. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/fixture_with_javascript_block.html +1 -0
  311. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/javascripts/jasmine_javascript_click.js +1 -0
  312. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/javascripts/jasmine_javascript_hover.js +1 -0
  313. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/json/jasmine_json_test.json +1 -0
  314. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/real_non_mocked_fixture.html +1 -0
  315. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/real_non_mocked_fixture_style.css +1 -0
  316. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/suites/jasmine-jquery-spec.js +1782 -0
  317. data/spec_app/vendor/assets/bower_components/jquery/.bower.json +37 -0
  318. data/spec_app/vendor/assets/bower_components/jquery/MIT-LICENSE.txt +21 -0
  319. data/spec_app/vendor/assets/bower_components/jquery/bower.json +27 -0
  320. data/spec_app/vendor/assets/bower_components/jquery/dist/jquery.js +9205 -0
  321. data/spec_app/vendor/assets/bower_components/jquery/dist/jquery.min.js +5 -0
  322. data/spec_app/vendor/assets/bower_components/jquery/dist/jquery.min.map +1 -0
  323. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/jsonp.js +89 -0
  324. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/load.js +75 -0
  325. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/parseJSON.js +13 -0
  326. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/parseXML.js +28 -0
  327. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/script.js +64 -0
  328. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/var/nonce.js +5 -0
  329. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/var/rquery.js +3 -0
  330. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/xhr.js +136 -0
  331. data/spec_app/vendor/assets/bower_components/jquery/src/ajax.js +786 -0
  332. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/attr.js +141 -0
  333. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/classes.js +158 -0
  334. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/prop.js +94 -0
  335. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/support.js +35 -0
  336. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/val.js +161 -0
  337. data/spec_app/vendor/assets/bower_components/jquery/src/attributes.js +11 -0
  338. data/spec_app/vendor/assets/bower_components/jquery/src/callbacks.js +205 -0
  339. data/spec_app/vendor/assets/bower_components/jquery/src/core/access.js +60 -0
  340. data/spec_app/vendor/assets/bower_components/jquery/src/core/init.js +123 -0
  341. data/spec_app/vendor/assets/bower_components/jquery/src/core/parseHTML.js +39 -0
  342. data/spec_app/vendor/assets/bower_components/jquery/src/core/ready.js +97 -0
  343. data/spec_app/vendor/assets/bower_components/jquery/src/core/var/rsingleTag.js +4 -0
  344. data/spec_app/vendor/assets/bower_components/jquery/src/core.js +497 -0
  345. data/spec_app/vendor/assets/bower_components/jquery/src/css/addGetHookIf.js +22 -0
  346. data/spec_app/vendor/assets/bower_components/jquery/src/css/curCSS.js +57 -0
  347. data/spec_app/vendor/assets/bower_components/jquery/src/css/defaultDisplay.js +70 -0
  348. data/spec_app/vendor/assets/bower_components/jquery/src/css/hiddenVisibleSelectors.js +15 -0
  349. data/spec_app/vendor/assets/bower_components/jquery/src/css/support.js +96 -0
  350. data/spec_app/vendor/assets/bower_components/jquery/src/css/swap.js +28 -0
  351. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/cssExpand.js +3 -0
  352. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/getStyles.js +12 -0
  353. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/isHidden.js +13 -0
  354. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/rmargin.js +3 -0
  355. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/rnumnonpx.js +5 -0
  356. data/spec_app/vendor/assets/bower_components/jquery/src/css.js +450 -0
  357. data/spec_app/vendor/assets/bower_components/jquery/src/data/Data.js +181 -0
  358. data/spec_app/vendor/assets/bower_components/jquery/src/data/accepts.js +20 -0
  359. data/spec_app/vendor/assets/bower_components/jquery/src/data/var/data_priv.js +5 -0
  360. data/spec_app/vendor/assets/bower_components/jquery/src/data/var/data_user.js +5 -0
  361. data/spec_app/vendor/assets/bower_components/jquery/src/data.js +178 -0
  362. data/spec_app/vendor/assets/bower_components/jquery/src/deferred.js +149 -0
  363. data/spec_app/vendor/assets/bower_components/jquery/src/deprecated.js +13 -0
  364. data/spec_app/vendor/assets/bower_components/jquery/src/dimensions.js +50 -0
  365. data/spec_app/vendor/assets/bower_components/jquery/src/effects/Tween.js +114 -0
  366. data/spec_app/vendor/assets/bower_components/jquery/src/effects/animatedSelector.js +13 -0
  367. data/spec_app/vendor/assets/bower_components/jquery/src/effects.js +648 -0
  368. data/spec_app/vendor/assets/bower_components/jquery/src/event/ajax.js +13 -0
  369. data/spec_app/vendor/assets/bower_components/jquery/src/event/alias.js +39 -0
  370. data/spec_app/vendor/assets/bower_components/jquery/src/event/support.js +9 -0
  371. data/spec_app/vendor/assets/bower_components/jquery/src/event.js +868 -0
  372. data/spec_app/vendor/assets/bower_components/jquery/src/exports/amd.js +24 -0
  373. data/spec_app/vendor/assets/bower_components/jquery/src/exports/global.js +32 -0
  374. data/spec_app/vendor/assets/bower_components/jquery/src/intro.js +44 -0
  375. data/spec_app/vendor/assets/bower_components/jquery/src/jquery.js +37 -0
  376. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation/_evalUrl.js +18 -0
  377. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation/support.js +32 -0
  378. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation/var/rcheckableType.js +3 -0
  379. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation.js +580 -0
  380. data/spec_app/vendor/assets/bower_components/jquery/src/offset.js +207 -0
  381. data/spec_app/vendor/assets/bower_components/jquery/src/outro.js +1 -0
  382. data/spec_app/vendor/assets/bower_components/jquery/src/queue/delay.js +22 -0
  383. data/spec_app/vendor/assets/bower_components/jquery/src/queue.js +142 -0
  384. data/spec_app/vendor/assets/bower_components/jquery/src/selector-native.js +172 -0
  385. data/spec_app/vendor/assets/bower_components/jquery/src/selector-sizzle.js +14 -0
  386. data/spec_app/vendor/assets/bower_components/jquery/src/selector.js +1 -0
  387. data/spec_app/vendor/assets/bower_components/jquery/src/serialize.js +111 -0
  388. data/spec_app/vendor/assets/bower_components/jquery/src/sizzle/dist/sizzle.js +2067 -0
  389. data/spec_app/vendor/assets/bower_components/jquery/src/sizzle/dist/sizzle.min.js +3 -0
  390. data/spec_app/vendor/assets/bower_components/jquery/src/sizzle/dist/sizzle.min.map +1 -0
  391. data/spec_app/vendor/assets/bower_components/jquery/src/traversing/findFilter.js +100 -0
  392. data/spec_app/vendor/assets/bower_components/jquery/src/traversing/var/rneedsContext.js +6 -0
  393. data/spec_app/vendor/assets/bower_components/jquery/src/traversing.js +199 -0
  394. data/spec_app/vendor/assets/bower_components/jquery/src/var/arr.js +3 -0
  395. data/spec_app/vendor/assets/bower_components/jquery/src/var/class2type.js +4 -0
  396. data/spec_app/vendor/assets/bower_components/jquery/src/var/concat.js +5 -0
  397. data/spec_app/vendor/assets/bower_components/jquery/src/var/hasOwn.js +5 -0
  398. data/spec_app/vendor/assets/bower_components/jquery/src/var/indexOf.js +5 -0
  399. data/spec_app/vendor/assets/bower_components/jquery/src/var/pnum.js +3 -0
  400. data/spec_app/vendor/assets/bower_components/jquery/src/var/push.js +5 -0
  401. data/spec_app/vendor/assets/bower_components/jquery/src/var/rnotwhite.js +3 -0
  402. data/spec_app/vendor/assets/bower_components/jquery/src/var/slice.js +5 -0
  403. data/spec_app/vendor/assets/bower_components/jquery/src/var/strundefined.js +3 -0
  404. data/spec_app/vendor/assets/bower_components/jquery/src/var/support.js +4 -0
  405. data/spec_app/vendor/assets/bower_components/jquery/src/var/toString.js +5 -0
  406. data/spec_app/vendor/assets/bower_components/jquery/src/wrap.js +79 -0
  407. metadata +386 -6
  408. data/lib/assets/javascripts/up/index.js +0 -13
  409. data/spec_app/app/assets/stylesheets/blocks/field_with_errors.css.sass +0 -5
data/dist/up.js ADDED
@@ -0,0 +1,2552 @@
1
+
2
+ /**
3
+ @module up
4
+ */
5
+
6
+ (function() {
7
+ window.up = {};
8
+
9
+ }).call(this);
10
+
11
+ /**
12
+ Utility functions
13
+ =================
14
+
15
+ All methods in this module are for internal use by the Up.js framework
16
+ and will frequently change between releases.
17
+
18
+ If you use them in your own code, you will get hurt.
19
+
20
+ @protected
21
+ @class up.util
22
+ */
23
+
24
+ (function() {
25
+ var __slice = [].slice;
26
+
27
+ up.util = (function() {
28
+ var $createElementFromSelector, ajax, castsToFalse, castsToTrue, clientSize, contains, copy, copyAttributes, createElement, createElementFromHtml, createSelectorFromElement, cssAnimate, detect, each, error, escapePressed, extend, findWithSelf, get, ifGiven, isArray, isBlank, isDefined, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, last, measure, merge, nextFrame, normalizeUrl, option, options, prependGhost, presence, presentAttr, select, temporaryCss, unwrap;
29
+ get = function(url, options) {
30
+ options = options || {};
31
+ options.url = url;
32
+ return ajax(options);
33
+ };
34
+ ajax = function(options) {
35
+ if (options.selector) {
36
+ options.headers = {
37
+ "X-Up-Selector": options.selector
38
+ };
39
+ }
40
+ return $.ajax(options);
41
+ };
42
+
43
+ /**
44
+ @method up.util.isStandardPort
45
+ @private
46
+ */
47
+ isStandardPort = function(protocol, port) {
48
+ return ((port === "" || port === "80") && protocol === 'http:') || (port === "443" && protocol === 'https:');
49
+ };
50
+
51
+ /**
52
+ Normalizes URLs, relative paths and absolute paths to a full URL
53
+ that can be checked for equality with other normalized URL.
54
+
55
+ By default hashes are ignored, search queries are included.
56
+
57
+ @method up.util.normalizeUrl
58
+ @param {Boolean} [options.hash=false]
59
+ @param {Boolean} [options.search=true]
60
+ @protected
61
+ */
62
+ normalizeUrl = function(urlOrAnchor, options) {
63
+ var anchor, normalized;
64
+ anchor = isString(urlOrAnchor) ? $('<a>').attr({
65
+ href: urlOrAnchor
66
+ }).get(0) : unwrap(urlOrAnchor);
67
+ normalized = anchor.protocol + "//" + anchor.hostname;
68
+ if (!isStandardPort(anchor.protocol, anchor.port)) {
69
+ normalized += ":" + anchor.port;
70
+ }
71
+ normalized += anchor.pathname;
72
+ if ((options != null ? options.hash : void 0) === true) {
73
+ normalized += anchor.hash;
74
+ }
75
+ if ((options != null ? options.search : void 0) !== false) {
76
+ normalized += anchor.search;
77
+ }
78
+ return normalized;
79
+ };
80
+ $createElementFromSelector = function(selector) {
81
+ var $element, $parent, $root, classes, conjunction, depthSelector, expression, html, id, iteration, path, tag, _i, _j, _len, _len1;
82
+ path = selector.split(/[ >]/);
83
+ $root = null;
84
+ for (iteration = _i = 0, _len = path.length; _i < _len; iteration = ++_i) {
85
+ depthSelector = path[iteration];
86
+ conjunction = depthSelector.match(/(^|\.|\#)[A-Za-z0-9\-_]+/g);
87
+ tag = "div";
88
+ classes = [];
89
+ id = null;
90
+ for (_j = 0, _len1 = conjunction.length; _j < _len1; _j++) {
91
+ expression = conjunction[_j];
92
+ switch (expression[0]) {
93
+ case ".":
94
+ classes.push(expression.substr(1));
95
+ break;
96
+ case "#":
97
+ id = expression.substr(1);
98
+ break;
99
+ default:
100
+ tag = expression;
101
+ }
102
+ }
103
+ html = "<" + tag;
104
+ if (classes.length) {
105
+ html += " class=\"" + classes.join(" ") + "\"";
106
+ }
107
+ if (id) {
108
+ html += " id=\"" + id + "\"";
109
+ }
110
+ html += ">";
111
+ $element = $(html);
112
+ if ($parent) {
113
+ $element.appendTo($parent);
114
+ }
115
+ if (iteration === 0) {
116
+ $root = $element;
117
+ }
118
+ $parent = $element;
119
+ }
120
+ return $root;
121
+ };
122
+ createElement = function(tagName, html) {
123
+ var element;
124
+ element = document.createElement(tagName);
125
+ element.innerHTML = html;
126
+ return element;
127
+ };
128
+ error = function() {
129
+ var args, message;
130
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
131
+ message = args.length === 1 && up.util.isString(args[0]) ? args[0] : JSON.stringify(args);
132
+ console.log.apply(console, ["[UP] Error: " + message].concat(__slice.call(args)));
133
+ alert(message);
134
+ throw message;
135
+ };
136
+ createSelectorFromElement = function($element) {
137
+ var classString, classes, id, klass, selector, _i, _len;
138
+ console.log("Creating selector from element", $element);
139
+ classes = (classString = $element.attr("class")) ? classString.split(" ") : [];
140
+ id = $element.attr("id");
141
+ selector = $element.prop("tagName").toLowerCase();
142
+ if (id) {
143
+ selector += "#" + id;
144
+ }
145
+ for (_i = 0, _len = classes.length; _i < _len; _i++) {
146
+ klass = classes[_i];
147
+ selector += "." + klass;
148
+ }
149
+ return selector;
150
+ };
151
+ createElementFromHtml = function(html) {
152
+ var htmlElementPattern, innerHtml, match;
153
+ htmlElementPattern = /<html>((?:.|\n)*)<\/html>/i;
154
+ innerHtml = void 0;
155
+ if (match = html.match(htmlElementPattern)) {
156
+ innerHtml = match[1];
157
+ } else {
158
+ innerHtml = "<html><body>" + html + "</body></html>";
159
+ }
160
+ return createElement('html', innerHtml);
161
+ };
162
+ extend = $.extend;
163
+ each = function(collection, block) {
164
+ var index, item, _i, _len, _results;
165
+ _results = [];
166
+ for (index = _i = 0, _len = collection.length; _i < _len; index = ++_i) {
167
+ item = collection[index];
168
+ _results.push(block(item, index));
169
+ }
170
+ return _results;
171
+ };
172
+ isNull = function(object) {
173
+ return object === null;
174
+ };
175
+ isUndefined = function(object) {
176
+ return object === void(0);
177
+ };
178
+ isDefined = function(object) {
179
+ return !isUndefined(object);
180
+ };
181
+ isMissing = function(object) {
182
+ return isUndefined(object) || isNull(object);
183
+ };
184
+ isGiven = function(object) {
185
+ return !isMissing(object);
186
+ };
187
+ isBlank = function(object) {
188
+ return isMissing(object) || (object.length === 0);
189
+ };
190
+ presence = function(object, checker) {
191
+ if (checker == null) {
192
+ checker = isPresent;
193
+ }
194
+ if (checker(object)) {
195
+ return object;
196
+ } else {
197
+ return null;
198
+ }
199
+ };
200
+ isPresent = function(object) {
201
+ return !isBlank(object);
202
+ };
203
+ isFunction = function(object) {
204
+ return typeof object === 'function';
205
+ };
206
+ isString = function(object) {
207
+ return typeof object === 'string';
208
+ };
209
+ isHash = function(object) {
210
+ return typeof object === 'object' && !!object;
211
+ };
212
+ isObject = function(object) {
213
+ return isHash(object) || (typeof object === 'function');
214
+ };
215
+ isJQuery = function(object) {
216
+ return object instanceof jQuery;
217
+ };
218
+ isPromise = function(object) {
219
+ return isFunction(object.then);
220
+ };
221
+ ifGiven = function(object) {
222
+ if (isGiven(object)) {
223
+ return object;
224
+ }
225
+ };
226
+ isArray = Array.isArray;
227
+ copy = function(object) {
228
+ if (isArray(object)) {
229
+ return object.slice();
230
+ } else {
231
+ return extend({}, object);
232
+ }
233
+ };
234
+ unwrap = function(object) {
235
+ if (isJQuery(object)) {
236
+ return object.get(0);
237
+ } else {
238
+ return object;
239
+ }
240
+ };
241
+ merge = function(object, otherObject) {
242
+ return extend(copy(object), otherObject);
243
+ };
244
+ options = function(object, defaults) {
245
+ var defaultValue, key, merged, value;
246
+ merged = object ? copy(object) : {};
247
+ if (defaults) {
248
+ for (key in defaults) {
249
+ defaultValue = defaults[key];
250
+ value = merged[key];
251
+ if (!isGiven(value)) {
252
+ merged[key] = defaultValue;
253
+ } else if (isObject(defaultValue) && isObject(value)) {
254
+ merged[key] = options(value, defaultValue);
255
+ }
256
+ }
257
+ }
258
+ return merged;
259
+ };
260
+
261
+ /**
262
+ Returns the first argument that is considered present.
263
+ If an argument is a function, it is called and the value is checked for presence.
264
+
265
+ This function is useful when you have multiple option sources and the value can be boolean.
266
+ In that case you cannot change the sources with a `||` operator
267
+ (since that doesn't short-circuit at `false`).
268
+
269
+ @method up.util.option
270
+ @param {Array} args...
271
+ */
272
+ option = function() {
273
+ var args;
274
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
275
+ return detect(args, function(arg) {
276
+ var value;
277
+ value = arg;
278
+ if (isFunction(value)) {
279
+ value = value();
280
+ }
281
+ return isPresent(value);
282
+ });
283
+ };
284
+ detect = function(array, tester) {
285
+ var match;
286
+ match = null;
287
+ array.every(function(element) {
288
+ if (tester(element)) {
289
+ match = element;
290
+ return false;
291
+ } else {
292
+ return true;
293
+ }
294
+ });
295
+ return match;
296
+ };
297
+ select = function(array, tester) {
298
+ var matches;
299
+ matches = [];
300
+ each(array, function(element) {
301
+ if (tester(element)) {
302
+ return matches.push(element);
303
+ }
304
+ });
305
+ return matches;
306
+ };
307
+ presentAttr = function() {
308
+ var $element, attrName, attrNames, values;
309
+ $element = arguments[0], attrNames = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
310
+ values = (function() {
311
+ var _i, _len, _results;
312
+ _results = [];
313
+ for (_i = 0, _len = attrNames.length; _i < _len; _i++) {
314
+ attrName = attrNames[_i];
315
+ _results.push($element.attr(attrName));
316
+ }
317
+ return _results;
318
+ })();
319
+ return detect(values, isPresent);
320
+ };
321
+ nextFrame = function(block) {
322
+ return setTimeout(block, 0);
323
+ };
324
+ last = function(array) {
325
+ return array[array.length - 1];
326
+ };
327
+ clientSize = function() {
328
+ var element;
329
+ element = document.documentElement;
330
+ return {
331
+ width: element.clientWidth,
332
+ height: element.clientHeight
333
+ };
334
+ };
335
+ temporaryCss = function($element, css, block) {
336
+ var memo, oldCss;
337
+ oldCss = $element.css(Object.keys(css));
338
+ $element.css(css);
339
+ memo = function() {
340
+ return $element.css(oldCss);
341
+ };
342
+ if (block) {
343
+ block();
344
+ return memo();
345
+ } else {
346
+ return memo;
347
+ }
348
+ };
349
+
350
+ /**
351
+ Animates the given element's CSS properties using CSS transitions.
352
+
353
+ @method up.util.cssAnimate
354
+ @param {Element|jQuery|String} elementOrSelector
355
+ The element to animate.
356
+ @param {Object} lastFrame
357
+ The CSS properties that should be transitioned to.
358
+ @param {Number} [opts.duration=300]
359
+ The duration of the animation, in milliseconds.
360
+ @param {Number} [opts.delay=0]
361
+ The delay before the animation starts, in milliseconds.
362
+ @param {String} [opts.easing='ease']
363
+ The timing function that controls the animation's acceleration.
364
+ See [W3C documentation](http://www.w3.org/TR/css3-transitions/#transition-timing-function)
365
+ for a list of pre-defined timing functions.
366
+ @return
367
+ A promise for the animation's end.
368
+ */
369
+ cssAnimate = function(elementOrSelector, lastFrame, opts) {
370
+ var $element, deferred, transition, withoutTransition;
371
+ opts = options(opts, {
372
+ duration: 300,
373
+ delay: 0,
374
+ easing: 'ease'
375
+ });
376
+ $element = $(elementOrSelector);
377
+ deferred = $.Deferred();
378
+ transition = {
379
+ 'transition-property': Object.keys(lastFrame).join(', '),
380
+ 'transition-duration': opts.duration + "ms",
381
+ 'transition-delay': opts.delay + "ms",
382
+ 'transition-timing-function': opts.easing
383
+ };
384
+ withoutTransition = temporaryCss($element, transition);
385
+ $element.css(lastFrame);
386
+ deferred.then(withoutTransition);
387
+ setTimeout((function() {
388
+ return deferred.resolve();
389
+ }), opts.duration + opts.delay);
390
+ return deferred.promise();
391
+ };
392
+ measure = function($element, options) {
393
+ var box, offset, viewport;
394
+ offset = $element.offset();
395
+ box = {
396
+ left: offset.left,
397
+ top: offset.top,
398
+ width: $element.outerWidth(),
399
+ height: $element.outerHeight()
400
+ };
401
+ if (options != null ? options.full : void 0) {
402
+ viewport = clientSize();
403
+ box.right = viewport.width - (box.left + box.width);
404
+ box.bottom = viewport.height - (box.top + box.height);
405
+ }
406
+ return box;
407
+ };
408
+ copyAttributes = function($source, $target) {
409
+ var attr, _i, _len, _ref, _results;
410
+ _ref = $source.get(0).attributes;
411
+ _results = [];
412
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
413
+ attr = _ref[_i];
414
+ if (attr.specified) {
415
+ _results.push($target.attr(attr.name, attr.value));
416
+ } else {
417
+ _results.push(void 0);
418
+ }
419
+ }
420
+ return _results;
421
+ };
422
+ prependGhost = function($element) {
423
+ var $ghost, dimensions;
424
+ dimensions = measure($element);
425
+ $ghost = $element.clone();
426
+ $ghost.find('script').remove();
427
+ $ghost.css({
428
+ right: '',
429
+ bottom: '',
430
+ margin: 0,
431
+ position: 'absolute'
432
+ });
433
+ $ghost.css(dimensions);
434
+ $ghost.addClass('up-ghost');
435
+ return $ghost.prependTo(document.body);
436
+ };
437
+ findWithSelf = function($element, selector) {
438
+ return $element.find(selector).addBack(selector);
439
+ };
440
+ escapePressed = function(event) {
441
+ return event.keyCode === 27;
442
+ };
443
+ contains = function(array, element) {
444
+ return array.indexOf(element) >= 0;
445
+ };
446
+ castsToTrue = function(object) {
447
+ return String(object) === "true";
448
+ };
449
+ castsToFalse = function(object) {
450
+ return String(object) === "false";
451
+ };
452
+ return {
453
+ presentAttr: presentAttr,
454
+ createElement: createElement,
455
+ normalizeUrl: normalizeUrl,
456
+ createElementFromHtml: createElementFromHtml,
457
+ $createElementFromSelector: $createElementFromSelector,
458
+ createSelectorFromElement: createSelectorFromElement,
459
+ get: get,
460
+ ajax: ajax,
461
+ extend: extend,
462
+ copy: copy,
463
+ merge: merge,
464
+ options: options,
465
+ option: option,
466
+ error: error,
467
+ each: each,
468
+ detect: detect,
469
+ select: select,
470
+ last: last,
471
+ isNull: isNull,
472
+ isDefined: isDefined,
473
+ isUndefined: isUndefined,
474
+ isGiven: isGiven,
475
+ isMissing: isMissing,
476
+ isPresent: isPresent,
477
+ isBlank: isBlank,
478
+ presence: presence,
479
+ isObject: isObject,
480
+ isFunction: isFunction,
481
+ isString: isString,
482
+ isJQuery: isJQuery,
483
+ isPromise: isPromise,
484
+ isHash: isHash,
485
+ ifGiven: ifGiven,
486
+ unwrap: unwrap,
487
+ nextFrame: nextFrame,
488
+ measure: measure,
489
+ temporaryCss: temporaryCss,
490
+ cssAnimate: cssAnimate,
491
+ prependGhost: prependGhost,
492
+ escapePressed: escapePressed,
493
+ copyAttributes: copyAttributes,
494
+ findWithSelf: findWithSelf,
495
+ contains: contains,
496
+ isArray: isArray,
497
+ castsToTrue: castsToTrue,
498
+ castsToFalse: castsToFalse
499
+ };
500
+ })();
501
+
502
+ }).call(this);
503
+
504
+ /**
505
+ Browser interface
506
+ =================
507
+
508
+ @class up.browser
509
+ */
510
+
511
+ (function() {
512
+ up.browser = (function() {
513
+ var url;
514
+ url = function() {
515
+ return location.href;
516
+ };
517
+ return {
518
+ url: url
519
+ };
520
+ })();
521
+
522
+ }).call(this);
523
+
524
+ /**
525
+ Framework events
526
+ ================
527
+
528
+ TODO: Write some documentation
529
+
530
+ This class is kind-of internal and in flux.
531
+ This might eventually be rolled into regular document events.
532
+
533
+ - `app:ready`
534
+ - `fragment:ready` with arguments `($fragment)`
535
+ - `fragment:destroy` with arguments `($fragment)`
536
+
537
+ @class up.bus
538
+ */
539
+
540
+ (function() {
541
+ var __slice = [].slice;
542
+
543
+ up.bus = (function() {
544
+ var callbacksByEvent, callbacksFor, defaultCallbacksByEvent, emit, listen, reset, snapshot;
545
+ callbacksByEvent = {};
546
+ defaultCallbacksByEvent = {};
547
+ callbacksFor = function(event) {
548
+ return callbacksByEvent[event] || (callbacksByEvent[event] = []);
549
+ };
550
+
551
+ /**
552
+ Makes a snapshot of the currently registered bus listeners,
553
+ to later be restored through [`up.bus.reset`](/up.bus#up.bus.reset)
554
+
555
+ @private
556
+ @method up.bus.snapshot
557
+ */
558
+ snapshot = function() {
559
+ var callbacks, event, _results;
560
+ defaultCallbacksByEvent = {};
561
+ _results = [];
562
+ for (event in callbacksByEvent) {
563
+ callbacks = callbacksByEvent[event];
564
+ _results.push(defaultCallbacksByEvent[event] = up.util.copy(callbacks));
565
+ }
566
+ return _results;
567
+ };
568
+
569
+ /**
570
+ Resets the list of registered event listeners to the
571
+ moment when the framework was booted.
572
+
573
+ @private
574
+ @method up.bus.reset
575
+ */
576
+ reset = function() {
577
+ return callbacksByEvent = up.util.copy(defaultCallbacksByEvent);
578
+ };
579
+
580
+ /**
581
+ Registers an event handler to be called when the given
582
+ event is triggered.
583
+
584
+ @method up.bus.listen
585
+ @param {String} eventName
586
+ The event name to match.
587
+ @param {Function} handler
588
+ The event handler to be called with the event arguments.
589
+ */
590
+ listen = function(eventName, handler) {
591
+ return callbacksFor(eventName).push(handler);
592
+ };
593
+
594
+ /**
595
+ Triggers an event.
596
+
597
+ @method up.bus.emit
598
+ @param {String} eventName
599
+ The name of the event.
600
+ @param {Anything...} args
601
+ The arguments that describe the event.
602
+ */
603
+ emit = function() {
604
+ var args, callbacks, eventName;
605
+ eventName = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
606
+ console.log("bus emitting", eventName, args);
607
+ callbacks = callbacksFor(eventName);
608
+ return up.util.each(callbacks, function(callback) {
609
+ return callback.apply(null, args);
610
+ });
611
+ };
612
+ listen('framework:ready', snapshot);
613
+ listen('framework:reset', reset);
614
+ return {
615
+ on: listen,
616
+ emit: emit
617
+ };
618
+ })();
619
+
620
+ }).call(this);
621
+
622
+ /**
623
+ Changing page fragments programmatically
624
+ ========================================
625
+
626
+ TODO: Write some documentation
627
+
628
+
629
+ @class up.flow
630
+ */
631
+
632
+ (function() {
633
+ up.flow = (function() {
634
+ var autofocus, destroy, elementsInserted, implant, implantSteps, reload, replace, reset, setSource, source, swapElements, u;
635
+ u = up.util;
636
+ setSource = function(element, sourceUrl) {
637
+ var $element;
638
+ $element = $(element);
639
+ if (u.isPresent(sourceUrl)) {
640
+ sourceUrl = u.normalizeUrl(sourceUrl);
641
+ }
642
+ return $element.attr("up-source", sourceUrl);
643
+ };
644
+ source = function(element) {
645
+ var $element;
646
+ $element = $(element).closest("[up-source]");
647
+ return u.presence($element.attr("up-source")) || up.browser.url();
648
+ };
649
+
650
+ /**
651
+ Replaces elements on the current page with corresponding elements
652
+ from a new page fetched from the server.
653
+
654
+ The current and new elements must have the same CSS selector.
655
+
656
+ @method up.replace
657
+ @param {String|Element|jQuery} selectorOrElement
658
+ The CSS selector to update. You can also pass a DOM element or jQuery element
659
+ here, in which case a selector will be inferred from the element's class and ID.
660
+ @param {String} url
661
+ The URL to fetch from the server.
662
+ @param {String} [options.title]
663
+ @param {String|Boolean} [options.history=true]
664
+ If a `String` is given, it is used as the URL the browser's location bar and history.
665
+ If omitted or true, the `url` argument will be used.
666
+ If set to `false`, the history will remain unchanged.
667
+ @param {String|Boolean} [options.source=true]
668
+ @param {String} [options.transition]
669
+ @param {String} [options.historyMethod='push']
670
+ */
671
+ replace = function(selectorOrElement, url, options) {
672
+ var selector;
673
+ options = u.options(options);
674
+ selector = u.presence(selectorOrElement) ? selectorOrElement : u.createSelectorFromElement($(selectorOrElement));
675
+ if (u.isMissing(options.history) || u.castsToTrue(options.history)) {
676
+ options.history = url;
677
+ }
678
+ if (u.isMissing(options.source) || u.castsToTrue(options.source)) {
679
+ options.source = url;
680
+ }
681
+ return u.get(url, {
682
+ selector: selector
683
+ }).done(function(html) {
684
+ return implant(selector, html, options);
685
+ }).fail(u.error);
686
+ };
687
+
688
+ /**
689
+ Replaces the given selector with the same selector from the given HTML string.
690
+
691
+ @method up.flow.implant
692
+ @protected
693
+ @param {String} selector
694
+ @param {String} html
695
+ @param {String} [options.title]
696
+ @param {String} [options.source]
697
+ @param {Object} [options.transition]
698
+ @param {String} [options.history]
699
+ @param {String} [options.historyMethod='push']
700
+ */
701
+ implant = function(selector, html, options) {
702
+ var $new, $old, fragment, htmlElement, step, _i, _len, _ref, _ref1, _results;
703
+ options = u.options(options, {
704
+ historyMethod: 'push'
705
+ });
706
+ htmlElement = u.createElementFromHtml(html);
707
+ options.title || (options.title = (_ref = htmlElement.querySelector("title")) != null ? _ref.textContent : void 0);
708
+ _ref1 = implantSteps(selector, options);
709
+ _results = [];
710
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
711
+ step = _ref1[_i];
712
+ $old = u.presence($(".up-popup " + step.selector)) || u.presence($(".up-modal " + step.selector)) || u.presence($(step.selector));
713
+ if (fragment = htmlElement.querySelector(step.selector)) {
714
+ $new = $(fragment);
715
+ _results.push(swapElements($old, $new, step.pseudoClass, step.transition, options));
716
+ } else {
717
+ _results.push(u.error("Could not find selector (" + step.selector + ") in response (" + html + ")"));
718
+ }
719
+ }
720
+ return _results;
721
+ };
722
+ elementsInserted = function($new, options) {
723
+ return $new.each(function() {
724
+ var $element;
725
+ $element = $(this);
726
+ if (typeof options.insert === "function") {
727
+ options.insert($element);
728
+ }
729
+ if (options.history) {
730
+ if (options.title) {
731
+ document.title = options.title;
732
+ }
733
+ up.history[options.historyMethod](options.history);
734
+ }
735
+ setSource($element, u.presence(options.source) || options.history);
736
+ autofocus($element);
737
+ return up.ready($element);
738
+ });
739
+ };
740
+ swapElements = function($old, $new, pseudoClass, transition, options) {
741
+ var $addedChildren, insertionMethod;
742
+ transition || (transition = 'none');
743
+ if (pseudoClass) {
744
+ insertionMethod = pseudoClass === 'before' ? 'prepend' : 'append';
745
+ $addedChildren = $new.children();
746
+ $old[insertionMethod]($new.contents());
747
+ u.copyAttributes($new, $old);
748
+ elementsInserted($addedChildren, options);
749
+ return up.animate($new, transition);
750
+ } else {
751
+ return destroy($old, {
752
+ animation: function() {
753
+ $new.insertAfter($old);
754
+ elementsInserted($new, options);
755
+ if ($old.is('body') && transition !== 'none') {
756
+ u.error('Cannot apply transitions to body-elements', transition);
757
+ }
758
+ return up.morph($old, $new, transition);
759
+ }
760
+ });
761
+ }
762
+ };
763
+ implantSteps = function(selector, options) {
764
+ var comma, disjunction, i, selectorAtom, selectorParts, transition, transitionString, transitions, _i, _len, _results;
765
+ transitionString = options.transition || options.animation || 'none';
766
+ comma = /\ *,\ */;
767
+ disjunction = selector.split(comma);
768
+ if (u.isPresent(transitionString)) {
769
+ transitions = transitionString.split(comma);
770
+ }
771
+ _results = [];
772
+ for (i = _i = 0, _len = disjunction.length; _i < _len; i = ++_i) {
773
+ selectorAtom = disjunction[i];
774
+ selectorParts = selectorAtom.match(/^(.+?)(?:\:(before|after))?$/);
775
+ transition = transitions[i] || u.last(transitions);
776
+ _results.push({
777
+ selector: selectorParts[1],
778
+ pseudoClass: selectorParts[2],
779
+ transition: transition
780
+ });
781
+ }
782
+ return _results;
783
+ };
784
+ autofocus = function($element) {
785
+ var $control, selector;
786
+ selector = '[autofocus]:last';
787
+ $control = u.findWithSelf($element, selector);
788
+ if ($control.length && $control.get(0) !== document.activeElement) {
789
+ return $control.focus();
790
+ }
791
+ };
792
+
793
+ /**
794
+ Destroys the given element or selector.
795
+ Takes care that all destructors, if any, are called.
796
+
797
+ @method up.destroy
798
+ @param {String|Element|jQuery} selectorOrElement
799
+ @param {String|Function|Object} [options.animation]
800
+ @param {String} [options.url]
801
+ @param {String} [options.title]
802
+ */
803
+ destroy = function(selectorOrElement, options) {
804
+ var $element, animationPromise;
805
+ $element = $(selectorOrElement);
806
+ options = u.options(options, {
807
+ animation: 'none'
808
+ });
809
+ $element.addClass('up-destroying');
810
+ if (u.isPresent(options.url)) {
811
+ up.history.push(options.url);
812
+ }
813
+ if (u.isPresent(options.title)) {
814
+ document.title = options.title;
815
+ }
816
+ up.bus.emit('fragment:destroy', $element);
817
+ animationPromise = u.presence(options.animation, u.isPromise) || up.motion.animate($element, options.animation);
818
+ return animationPromise.then(function() {
819
+ return $element.remove();
820
+ });
821
+ };
822
+
823
+ /**
824
+ Replaces the given selector or element with a fresh copy
825
+ fetched from the server.
826
+
827
+ @method up.reload
828
+ @param {String|Element|jQuery} selectorOrElement
829
+ */
830
+ reload = function(selectorOrElement) {
831
+ var sourceUrl;
832
+ sourceUrl = source(selectorOrElement);
833
+ return replace(selectorOrElement, sourceUrl);
834
+ };
835
+
836
+ /**
837
+ Resets Up.js to the state when it was booted.
838
+ All custom event handlers, animations, etc. that have been registered
839
+ will be discarded.
840
+
841
+ This is an internal method for to enable unit testing.
842
+ Don't use this in production.
843
+
844
+ @protected
845
+ @method up.reset
846
+ */
847
+ reset = function() {
848
+ return up.bus.emit('framework:reset');
849
+ };
850
+ up.bus.on('app:ready', function() {
851
+ return setSource(document.body, up.browser.url());
852
+ });
853
+ return {
854
+ replace: replace,
855
+ reload: reload,
856
+ destroy: destroy,
857
+ implant: implant,
858
+ reset: reset
859
+ };
860
+ })();
861
+
862
+ up.replace = up.flow.replace;
863
+
864
+ up.reload = up.flow.reload;
865
+
866
+ up.destroy = up.flow.destroy;
867
+
868
+ up.reset = up.flow.reset;
869
+
870
+ }).call(this);
871
+
872
+ /**
873
+ Registering behavior and custom elements
874
+ ========================================
875
+
876
+ TODO: Write some documentation
877
+
878
+ @class up.magic
879
+ */
880
+
881
+ (function() {
882
+ up.magic = (function() {
883
+ var DESTROYABLE_CLASS, DESTROYER_KEY, awaken, awakeners, compile, defaultAwakeners, defaultLiveDescriptions, destroy, live, liveDescriptions, onEscape, ready, reset, snapshot, util;
884
+ util = up.util;
885
+ DESTROYABLE_CLASS = 'up-destroyable';
886
+ DESTROYER_KEY = 'up-destroyer';
887
+
888
+ /**
889
+ Binds an event handler to the document,
890
+ which will be executed whenever the given event
891
+ is triggered on the given selector.
892
+
893
+ @method up.on
894
+ @param {String} events
895
+ A space-separated list of event names to bind.
896
+ @param {String} selector
897
+ The selector an on which the event must be triggered.
898
+ @param {Function} behavior
899
+ The handler that should be called.
900
+ */
901
+ liveDescriptions = [];
902
+ defaultLiveDescriptions = null;
903
+ live = function(events, selector, behavior) {
904
+ var description, _ref;
905
+ description = [
906
+ events, selector, function(event) {
907
+ return behavior.apply(this, [event, $(this)]);
908
+ }
909
+ ];
910
+ liveDescriptions.push(description);
911
+ return (_ref = $(document)).on.apply(_ref, description);
912
+ };
913
+
914
+ /**
915
+ Registers a function to be called whenever an element with
916
+ the given selector is inserted into the DOM through Up.js.
917
+
918
+ @method up.awaken
919
+ @param {String} selector
920
+ The selector to match.
921
+ @param {Function($element)} awakener
922
+ The function to call when a matching element is inserted.
923
+ The function takes the new element as the first argument (as a jQuery object).
924
+
925
+ The function may return another function that destroys the awakened
926
+ object when it is removed from the DOM, by clearing global state such as
927
+ time-outs and event handlers bound to the document.
928
+ */
929
+ awakeners = [];
930
+ defaultAwakeners = null;
931
+ awaken = function(selector, awakener) {
932
+ return awakeners.push({
933
+ selector: selector,
934
+ callback: awakener
935
+ });
936
+ };
937
+ compile = function($fragment) {
938
+ var awakener, _i, _len, _results;
939
+ console.log("Compiling fragment", $fragment, "with", awakeners);
940
+ _results = [];
941
+ for (_i = 0, _len = awakeners.length; _i < _len; _i++) {
942
+ awakener = awakeners[_i];
943
+ console.log("running", awakener.selector, "on", $fragment);
944
+ _results.push(util.findWithSelf($fragment, awakener.selector).each(function() {
945
+ var $element, destroyer;
946
+ $element = $(this);
947
+ destroyer = awakener.callback.apply(this, [$element]);
948
+ console.log("got destroyer", destroyer);
949
+ if (util.isFunction(destroyer)) {
950
+ $element.addClass(DESTROYABLE_CLASS);
951
+ return $element.data(DESTROYER_KEY, destroyer);
952
+ }
953
+ }));
954
+ }
955
+ return _results;
956
+ };
957
+ destroy = function($fragment) {
958
+ return util.findWithSelf($fragment, "." + DESTROYABLE_CLASS).each(function() {
959
+ var $element, destroyer;
960
+ $element = $(this);
961
+ destroyer = $element.data(DESTROYER_KEY);
962
+ return destroyer();
963
+ });
964
+ };
965
+
966
+ /**
967
+ Makes a snapshot of the currently registered event listeners,
968
+ to later be restored through [`up.bus.reset`](/up.bus#up.bus.reset).
969
+
970
+ @private
971
+ @method up.magic.snapshot
972
+ */
973
+ snapshot = function() {
974
+ defaultLiveDescriptions = util.copy(liveDescriptions);
975
+ return defaultAwakeners = util.copy(awakeners);
976
+ };
977
+
978
+ /**
979
+ Resets the list of registered event listeners to the
980
+ moment when the framework was booted.
981
+
982
+ @private
983
+ @method up.magic.reset
984
+ */
985
+ reset = function() {
986
+ var description, _i, _len, _ref;
987
+ for (_i = 0, _len = liveDescriptions.length; _i < _len; _i++) {
988
+ description = liveDescriptions[_i];
989
+ if (!util.contains(defaultLiveDescriptions, description)) {
990
+ (_ref = $(document)).off.apply(_ref, description);
991
+ }
992
+ }
993
+ liveDescriptions = util.copy(defaultLiveDescriptions);
994
+ return awakeners = util.copy(defaultAwakeners);
995
+ };
996
+
997
+ /**
998
+ Sends a notification that the given element has been inserted
999
+ into the DOM. This causes Up.js to compile the fragment (apply
1000
+ event listeners, etc.).
1001
+
1002
+ This method is called automatically if you change elements through
1003
+ other Up.js methods. You will only need to call this if you
1004
+ manipulate the DOM without going through Up.js.
1005
+
1006
+ @method up.ready
1007
+ @param {String|Element|jQuery} selectorOrFragment
1008
+ */
1009
+ ready = function(selectorOrFragment) {
1010
+ var $fragment;
1011
+ $fragment = $(selectorOrFragment);
1012
+ up.bus.emit('fragment:ready', $fragment);
1013
+ return $fragment;
1014
+ };
1015
+ onEscape = function(handler) {
1016
+ return live('keydown', 'body', function(event) {
1017
+ if (util.escapePressed(event)) {
1018
+ return handler(event);
1019
+ }
1020
+ });
1021
+ };
1022
+ up.bus.on('app:ready', (function() {
1023
+ return ready(document.body);
1024
+ }));
1025
+ up.bus.on('fragment:ready', compile);
1026
+ up.bus.on('fragment:destroy', destroy);
1027
+ up.bus.on('framework:ready', snapshot);
1028
+ up.bus.on('framework:reset', reset);
1029
+ return {
1030
+ awaken: awaken,
1031
+ on: live,
1032
+ ready: ready,
1033
+ onEscape: onEscape
1034
+ };
1035
+ })();
1036
+
1037
+ up.awaken = up.magic.awaken;
1038
+
1039
+ up.on = up.magic.on;
1040
+
1041
+ up.ready = up.magic.ready;
1042
+
1043
+ }).call(this);
1044
+
1045
+ /**
1046
+ Manipulating the browser history
1047
+ =======
1048
+
1049
+ TODO: Write some documentation
1050
+
1051
+ @class up.history
1052
+ */
1053
+
1054
+ (function() {
1055
+ up.history = (function() {
1056
+ var isCurrentUrl, manipulate, pop, push, replace, u;
1057
+ u = up.util;
1058
+ isCurrentUrl = function(url) {
1059
+ return u.normalizeUrl(url, {
1060
+ hash: true
1061
+ }) === u.normalizeUrl(up.browser.url(), {
1062
+ hash: true
1063
+ });
1064
+ };
1065
+
1066
+ /**
1067
+ @method up.history.replace
1068
+ @param {String} url
1069
+ @protected
1070
+ */
1071
+ replace = function(url) {
1072
+ if (!isCurrentUrl(url)) {
1073
+ return manipulate("replace", url);
1074
+ }
1075
+ };
1076
+
1077
+ /**
1078
+ @method up.history.push
1079
+ @param {String} url
1080
+ @protected
1081
+ */
1082
+ push = function(url) {
1083
+ if (!isCurrentUrl(url)) {
1084
+ return manipulate("push", url);
1085
+ }
1086
+ };
1087
+ manipulate = function(method, url) {
1088
+ method += "State";
1089
+ return window.history[method]({
1090
+ fromUp: true
1091
+ }, '', url);
1092
+ };
1093
+ pop = function(event) {
1094
+ var state;
1095
+ state = event.originalEvent.state;
1096
+ console.log("popping state", state);
1097
+ console.log("current href", up.browser.url());
1098
+ if (state != null ? state.fromUp : void 0) {
1099
+ return up.visit(up.browser.url(), {
1100
+ historyMethod: 'replace'
1101
+ });
1102
+ } else {
1103
+ return console.log("null state");
1104
+ }
1105
+ };
1106
+ setTimeout((function() {
1107
+ $(window).on("popstate", pop);
1108
+ return replace(up.browser.url());
1109
+ }), 200);
1110
+ return {
1111
+ push: push,
1112
+ replace: replace
1113
+ };
1114
+ })();
1115
+
1116
+ }).call(this);
1117
+
1118
+ /**
1119
+ Animation and transitions
1120
+ =========================
1121
+
1122
+ TODO: Write some documentation.
1123
+
1124
+ @class up.motion
1125
+ */
1126
+
1127
+ (function() {
1128
+ up.motion = (function() {
1129
+ var animate, animation, animations, assertIsPromise, defaultAnimations, defaultOptions, defaultTransitions, findAnimation, morph, none, reset, snapshot, transition, transitions, u, withGhosts;
1130
+ u = up.util;
1131
+ defaultOptions = {
1132
+ duration: 300,
1133
+ delay: 0,
1134
+ easing: 'ease'
1135
+ };
1136
+ animations = {};
1137
+ defaultAnimations = {};
1138
+ transitions = {};
1139
+ defaultTransitions = {};
1140
+
1141
+ /**
1142
+ Animates an element.
1143
+
1144
+ The following animations are pre-registered:
1145
+
1146
+ - `fade-in`
1147
+ - `fade-out`
1148
+ - `move-to-top`
1149
+ - `move-from-top`
1150
+ - `move-to-bottom`
1151
+ - `move-from-bottom`
1152
+ - `move-to-left`
1153
+ - `move-from-left`
1154
+ - `move-to-right`
1155
+ - `move-from-right`
1156
+ - `none`
1157
+
1158
+ @method up.animate
1159
+ @param {Element|jQuery|String} elementOrSelector
1160
+ @param {String|Function|Object} animation
1161
+ @param {Number} [options.duration]
1162
+ @param {String} [options.easing]
1163
+ @param {Number} [options.delay]
1164
+ @return {Promise}
1165
+ A promise for the animation's end.
1166
+ */
1167
+ animate = function(elementOrSelector, animation, options) {
1168
+ var $element;
1169
+ $element = $(elementOrSelector);
1170
+ options = u.options(options, defaultOptions);
1171
+ if (u.isFunction(animation)) {
1172
+ return assertIsPromise(animation($element, options), ["Animation did not return a Promise", animation]);
1173
+ } else if (u.isString(animation)) {
1174
+ return animate($element, findAnimation(animation), options);
1175
+ } else if (u.isHash(animation)) {
1176
+ return u.cssAnimate($element, animation, options);
1177
+ } else {
1178
+ return u.error("Unknown animation type", animation);
1179
+ }
1180
+ };
1181
+ findAnimation = function(name) {
1182
+ return animations[name] || u.error("Unknown animation", animation);
1183
+ };
1184
+ withGhosts = function($old, $new, block) {
1185
+ var $newGhost, $oldGhost, newCssMemo, promise;
1186
+ $oldGhost = null;
1187
+ $newGhost = null;
1188
+ u.temporaryCss($new, {
1189
+ display: 'none'
1190
+ }, function() {
1191
+ return $oldGhost = u.prependGhost($old).addClass('up-destroying');
1192
+ });
1193
+ u.temporaryCss($old, {
1194
+ display: 'none'
1195
+ }, function() {
1196
+ return $newGhost = u.prependGhost($new);
1197
+ });
1198
+ $old.css({
1199
+ visibility: 'hidden'
1200
+ });
1201
+ newCssMemo = u.temporaryCss($new, {
1202
+ display: 'none'
1203
+ });
1204
+ promise = block($oldGhost, $newGhost);
1205
+ return promise.then(function() {
1206
+ $oldGhost.remove();
1207
+ $newGhost.remove();
1208
+ $old.css({
1209
+ display: 'none'
1210
+ });
1211
+ return newCssMemo();
1212
+ });
1213
+ };
1214
+ assertIsPromise = function(object, messageParts) {
1215
+ u.isPromise(object) || u.error.apply(u, messageParts);
1216
+ return object;
1217
+ };
1218
+
1219
+ /**
1220
+ Performs a transition between two elements.
1221
+
1222
+ The following transitions are pre-registered:
1223
+
1224
+ - `cross-fade`
1225
+ - `move-top`
1226
+ - `move-bottom`
1227
+ - `move-left`
1228
+ - `move-right`
1229
+ - `none`
1230
+
1231
+ You can also compose a transition from two animation names
1232
+ separated by a slash character (`/`):
1233
+
1234
+ - `move-to-bottom/fade-in`
1235
+ - `move-to-left/move-from-top`
1236
+
1237
+ @method up.morph
1238
+ @param {Element|jQuery|String} source
1239
+ @param {Element|jQuery|String} target
1240
+ @param {Function|String} transitionOrName
1241
+ @param {Number} [options.duration]
1242
+ @param {String} [options.easing]
1243
+ @param {Number} [options.delay]
1244
+ @return {Promise}
1245
+ A promise for the transition's end.
1246
+ */
1247
+ morph = function(source, target, transitionOrName, options) {
1248
+ var $new, $old, animation, parts, transition;
1249
+ options = u.options(defaultOptions);
1250
+ $old = $(source);
1251
+ $new = $(target);
1252
+ transition = u.presence(transitionOrName, u.isFunction) || transitions[transitionOrName];
1253
+ if (transition) {
1254
+ return withGhosts($old, $new, function($oldGhost, $newGhost) {
1255
+ return assertIsPromise(transition($oldGhost, $newGhost, options), ["Transition did not return a promise", transitionOrName]);
1256
+ });
1257
+ } else if (animation = animations[transitionOrName]) {
1258
+ $old.hide();
1259
+ return animate($new, animation, options);
1260
+ } else if (u.isString(transitionOrName) && transitionOrName.indexOf('/') >= 0) {
1261
+ parts = transitionOrName.split('/');
1262
+ transition = function($old, $new, options) {
1263
+ return $.when(animate($old, parts[0], options), animate($new, parts[1], options));
1264
+ };
1265
+ return morph($old, $new, transition, options);
1266
+ } else {
1267
+ return u.error("Unknown transition: " + transitionOrName);
1268
+ }
1269
+ };
1270
+
1271
+ /**
1272
+ Defines a named transition.
1273
+
1274
+ @method up.transition
1275
+ @param {String} name
1276
+ @param {Function} transition
1277
+ */
1278
+ transition = function(name, transition) {
1279
+ return transitions[name] = transition;
1280
+ };
1281
+
1282
+ /**
1283
+ Defines a named animation.
1284
+
1285
+ @method up.animation
1286
+ @param {String} name
1287
+ @param {Function} animation
1288
+ */
1289
+ animation = function(name, animation) {
1290
+ return animations[name] = animation;
1291
+ };
1292
+ snapshot = function() {
1293
+ defaultAnimations = u.copy(animations);
1294
+ return defaultTransitions = u.copy(transitions);
1295
+ };
1296
+ reset = function() {
1297
+ animations = u.copy(defaultAnimations);
1298
+ return transitions = u.copy(defaultTransitions);
1299
+ };
1300
+
1301
+ /**
1302
+ Returns a no-op animation or transition which has no visual effects
1303
+ and completes instantly.
1304
+
1305
+ @method up.motion.none
1306
+ @return {Promise}
1307
+ A resolved promise
1308
+ */
1309
+ none = function() {
1310
+ var deferred;
1311
+ deferred = $.Deferred();
1312
+ deferred.resolve();
1313
+ return deferred.promise();
1314
+ };
1315
+ animation('none', none);
1316
+ animation('fade-in', function($ghost, options) {
1317
+ $ghost.css({
1318
+ opacity: 0
1319
+ });
1320
+ return animate($ghost, {
1321
+ opacity: 1
1322
+ }, options);
1323
+ });
1324
+ animation('fade-out', function($ghost, options) {
1325
+ $ghost.css({
1326
+ opacity: 1
1327
+ });
1328
+ return animate($ghost, {
1329
+ opacity: 0
1330
+ }, options);
1331
+ });
1332
+ animation('move-to-top', function($ghost, options) {
1333
+ $ghost.css({
1334
+ 'margin-top': '0%'
1335
+ });
1336
+ return animate($ghost, {
1337
+ 'margin-top': '-100%'
1338
+ }, options);
1339
+ });
1340
+ animation('move-from-top', function($ghost, options) {
1341
+ $ghost.css({
1342
+ 'margin-top': '-100%'
1343
+ });
1344
+ return animate($ghost, {
1345
+ 'margin-top': '0%'
1346
+ }, options);
1347
+ });
1348
+ animation('move-to-bottom', function($ghost, options) {
1349
+ $ghost.css({
1350
+ 'margin-top': '0%'
1351
+ });
1352
+ return animate($ghost, {
1353
+ 'margin-top': '100%'
1354
+ }, options);
1355
+ });
1356
+ animation('move-from-bottom', function($ghost, options) {
1357
+ $ghost.css({
1358
+ 'margin-top': '100%'
1359
+ });
1360
+ return animate($ghost, {
1361
+ 'margin-top': '0%'
1362
+ }, options);
1363
+ });
1364
+ animation('move-to-left', function($ghost, options) {
1365
+ $ghost.css({
1366
+ 'margin-left': '0%'
1367
+ });
1368
+ return animate($ghost, {
1369
+ 'margin-left': '-100%'
1370
+ }, options);
1371
+ });
1372
+ animation('move-from-left', function($ghost, options) {
1373
+ $ghost.css({
1374
+ 'margin-left': '-100%'
1375
+ });
1376
+ return animate($ghost, {
1377
+ 'margin-left': '0%'
1378
+ }, options);
1379
+ });
1380
+ animation('move-to-right', function($ghost, options) {
1381
+ $ghost.css({
1382
+ 'margin-left': '0%'
1383
+ });
1384
+ return animate($ghost, {
1385
+ 'margin-left': '100%'
1386
+ }, options);
1387
+ });
1388
+ animation('move-from-right', function($ghost, options) {
1389
+ $ghost.css({
1390
+ 'margin-left': '100%'
1391
+ });
1392
+ return animate($ghost, {
1393
+ 'margin-left': '0%'
1394
+ }, options);
1395
+ });
1396
+ animation('roll-down', function($ghost, options) {
1397
+ var fullHeight, styleMemo;
1398
+ fullHeight = $ghost.height();
1399
+ styleMemo = u.temporaryCss($ghost, {
1400
+ height: '0px',
1401
+ overflow: 'hidden'
1402
+ });
1403
+ return animate($ghost, {
1404
+ height: fullHeight + "px"
1405
+ }, options).then(styleMemo);
1406
+ });
1407
+ transition('none', none);
1408
+ transition('move-left', function($old, $new, options) {
1409
+ return $.when(animate($old, 'move-to-left', options), animate($new, 'move-from-right', options));
1410
+ });
1411
+ transition('move-right', function($old, $new, options) {
1412
+ return $.when(animate($old, 'move-to-right', options), animate($new, 'move-from-left', options));
1413
+ });
1414
+ transition('move-up', function($old, $new, options) {
1415
+ return $.when(animate($old, 'move-to-top', options), animate($new, 'move-from-bottom', options));
1416
+ });
1417
+ transition('move-down', function($old, $new, options) {
1418
+ return $.when(animate($old, 'move-to-bottom', options), animate($new, 'move-from-top', options));
1419
+ });
1420
+ transition('cross-fade', function($old, $new, options) {
1421
+ return $.when(animate($old, 'fade-out', options), animate($new, 'fade-in', options));
1422
+ });
1423
+ up.bus.on('framework:ready', snapshot);
1424
+ up.bus.on('framework:reset', reset);
1425
+ return {
1426
+ morph: morph,
1427
+ animate: animate,
1428
+ transition: transition,
1429
+ animation: animation,
1430
+ none: none
1431
+ };
1432
+ })();
1433
+
1434
+ up.transition = up.motion.transition;
1435
+
1436
+ up.animation = up.motion.animation;
1437
+
1438
+ up.morph = up.motion.morph;
1439
+
1440
+ up.animate = up.motion.animate;
1441
+
1442
+ }).call(this);
1443
+
1444
+ /**
1445
+ Linking to page fragments
1446
+ =========================
1447
+
1448
+ Just like in a classical web application, an Up.js app renders a series of *full HTML pages* on the server.
1449
+
1450
+ Let's say we are rendering three pages with a tabbed navigation to switch between screens:
1451
+
1452
+ ```
1453
+ /pages/a /pages/b /pages/c
1454
+
1455
+ +---+---+---+ +---+---+---+ +---+---+---+
1456
+ | A | B | C | | A | B | C | | A | B | C |
1457
+ | +-------- (click) +---+ +---- (click) +---+---+ |
1458
+ | | ======> | | ======> | |
1459
+ | Page A | | Page B | | Page C |
1460
+ | | | | | |
1461
+ +-----------| +-----------| +-----------|
1462
+ ```
1463
+
1464
+ Your HTML could look like this:
1465
+
1466
+ ```
1467
+ <nav>
1468
+ <a href="/pages/a">A</a>
1469
+ <a href="/pages/b">B</a>
1470
+ <a href="/pages/b">C</a>
1471
+ </nav>
1472
+
1473
+ <article>
1474
+ Page A
1475
+ </article>
1476
+ ```
1477
+
1478
+ Slow, full page loads. White flash during loading.
1479
+
1480
+
1481
+ Smoother flow by updating fragments
1482
+ -----------------------------------
1483
+
1484
+ In Up.js you annotate navigation links with an `up-target` attribute.
1485
+ The value of this attribute is a CSS selector that indicates which page
1486
+ fragment to update.
1487
+
1488
+ Since we only want to update the `<article>` tag, we will use `up-target="article"`:
1489
+
1490
+
1491
+ ```
1492
+ <nav>
1493
+ <a href="/pages/a" up-target="article">A</a>
1494
+ <a href="/pages/b" up-target="article">B</a>
1495
+ <a href="/pages/b" up-target="article">C</a>
1496
+ </nav>
1497
+ ```
1498
+
1499
+ Instead of `article` you can use any other CSS selector (e. g. `#main .article`).
1500
+
1501
+ With these `up-target` annotations Up.js only updates the targeted part of the screen.
1502
+ Javascript will not be reloaded, no white flash during a full page reload.
1503
+
1504
+
1505
+ Read on
1506
+ -------
1507
+ - You can [animate page transitions](/up.motion) by definining animations for fragments as they enter or leave the screen.
1508
+ - The `up-target` mechanism also works with [forms](/up.form).
1509
+ - As you switch through pages, Up.js will [update your browser's location bar and history](/up.history)
1510
+ - You can [open fragments in popups or modal dialogs](/up.modal).
1511
+ - You can give users [immediate feedback](/up.navigation) when a link is clicked or becomes current, without waiting for the server.
1512
+ - [Controlling Up.js pragmatically through Javascript](/up.flow)
1513
+ - [Defining custom tags and event handlers](/up.magic)
1514
+
1515
+
1516
+ @class up.link
1517
+ */
1518
+
1519
+ (function() {
1520
+ up.link = (function() {
1521
+ var follow, resolve, resolveUrl, u, visit;
1522
+ u = up.util;
1523
+
1524
+ /**
1525
+ Visits the given URL without a full page load.
1526
+ This is done by fetching `url` through an AJAX request
1527
+ and replacing the current `<body>` element with the response's `<body>` element.
1528
+
1529
+ @method up.visit
1530
+ @param {String} url
1531
+ The URL to visit.
1532
+ @param {Object} options
1533
+ See options for [`up.replace`](/up.flow#up.replace)
1534
+ @example
1535
+ up.visit('/users')
1536
+ */
1537
+ visit = function(url, options) {
1538
+ console.log("up.visit", url);
1539
+ return up.replace('body', url, options);
1540
+ };
1541
+
1542
+ /**
1543
+ Follows the given link via AJAX and replaces a CSS selector in the current page
1544
+ with corresponding elements from a new page fetched from the server.
1545
+
1546
+ @method up.follow
1547
+ @param {Element|jQuery|String} link
1548
+ An element or selector which resolves to an `<a>` tag
1549
+ or any element that is marked up with an `up-follow` attribute.
1550
+ @param {String} [options.target]
1551
+ The selector to replace.
1552
+ Defaults to the `up-target` attribute on `link`,
1553
+ or to `body` if such an attribute does not exist.
1554
+ @param {Function|String} [options.transition]
1555
+ A transition function or name.
1556
+ */
1557
+ follow = function(link, options) {
1558
+ var $link, selector, url;
1559
+ $link = $(link);
1560
+ options = u.options(options);
1561
+ url = u.option($link.attr('href'), $link.attr('up-follow'));
1562
+ selector = u.option(options.target, $link.attr('up-target'), 'body');
1563
+ options.transition = u.option(options.transition, $link.attr('up-transition'), $link.attr('up-animation'));
1564
+ options.history = u.option(options.history, $link.attr('up-history'));
1565
+ return up.replace(selector, url, options);
1566
+ };
1567
+ resolve = function(element) {
1568
+ var $element;
1569
+ $element = $(element);
1570
+ if ($element.is('a') || u.presentAttr($element, 'up-follow')) {
1571
+ return $element;
1572
+ } else {
1573
+ return $element.find('a:first');
1574
+ }
1575
+ };
1576
+ resolveUrl = function(element) {
1577
+ var $link;
1578
+ if ($link = resolve(element)) {
1579
+ return u.option($link.attr('href'), $link.attr('up-follow'));
1580
+ }
1581
+ };
1582
+
1583
+ /**
1584
+ Follows this link via AJAX and replaces a CSS selector in the current page
1585
+ with corresponding elements from a new page fetched from the server.
1586
+
1587
+ <a href="/users" up-target=".main">User list</a>
1588
+
1589
+ @method a[up-target]
1590
+ @ujs
1591
+ @param {String} up-target
1592
+ The CSS selector to replace
1593
+ */
1594
+ up.on('click', 'a[up-target]', function(event, $link) {
1595
+ event.preventDefault();
1596
+ return follow($link);
1597
+ });
1598
+
1599
+ /**
1600
+ If applied on a link, Follows this link via AJAX and replaces the
1601
+ current `<body>` element with the response's `<body>` element
1602
+
1603
+ <a href="/users" up-follow>User list</a>
1604
+
1605
+ You can also apply `[up-follow]` to any element that contains a link
1606
+ in order to enlarge the link's click area:
1607
+
1608
+ <div class="notification" up-follow>
1609
+ Record was saved!
1610
+ <a href="/records">Close</a>
1611
+ </div>
1612
+
1613
+ In the example above, clicking anywhere within `.notification` element
1614
+ would follow the `Close` link.
1615
+
1616
+ @method [up-follow]
1617
+ @ujs
1618
+ @param {String} [up-follow]
1619
+ */
1620
+ up.on('click', '[up-follow]', function(event, $element) {
1621
+ var childLinkClicked;
1622
+ childLinkClicked = function() {
1623
+ var $target, $targetLink;
1624
+ $target = $(event.target);
1625
+ $targetLink = $target.closest('a, [up-follow]');
1626
+ return $targetLink.length && $element.find($targetLink).length;
1627
+ };
1628
+ if (!childLinkClicked()) {
1629
+ event.preventDefault();
1630
+ return follow(resolve($element));
1631
+ }
1632
+ });
1633
+ return {
1634
+ visit: visit,
1635
+ follow: follow,
1636
+ resolve: resolve,
1637
+ resolveUrl: resolveUrl
1638
+ };
1639
+ })();
1640
+
1641
+ up.visit = up.link.visit;
1642
+
1643
+ up.follow = up.link.follow;
1644
+
1645
+ }).call(this);
1646
+
1647
+ /**
1648
+ Forms and controls
1649
+ ==================
1650
+
1651
+ TODO: Write some documentation
1652
+
1653
+ @class up.form
1654
+ */
1655
+
1656
+ (function() {
1657
+ up.form = (function() {
1658
+ var observe, submit, u;
1659
+ u = up.util;
1660
+
1661
+ /**
1662
+ Submits a form using the Up.js flow:
1663
+
1664
+ up.submit('form.new_user')
1665
+
1666
+ @method up.submit
1667
+ @param {Element|jQuery|String} formOrSelector
1668
+ A reference or selector for the form to submit.
1669
+ If the argument points to an element that is not a form,
1670
+ Up.js will search its ancestors for the closest form.
1671
+ @param {String} [options.target]
1672
+ @param {String} [options.failTarget]
1673
+ @param {Boolean|String} [options.history=true]
1674
+ Successful form submissions will add a history entry and change the browser's
1675
+ location bar if the form either uses the `GET` method or the response redirected
1676
+ to another page (this requires the `upjs-rails` gem).
1677
+ If want to prevent history changes in any case, set this to `false`.
1678
+ If you pass a `String`, it is used as the URL for the browser history.
1679
+ @param {String} [options.transition]
1680
+ @param {String} [options.failTransition]
1681
+ @return {Promise}
1682
+ A promise for the AJAX response
1683
+ */
1684
+ submit = function(formOrSelector, options) {
1685
+ var $form, failureSelector, failureTransition, historyOption, request, successSelector, successTransition, successUrl, _ref;
1686
+ $form = $(formOrSelector).closest('form');
1687
+ options = u.options(options);
1688
+ successSelector = u.option(options.target, $form.attr('up-target'), 'body');
1689
+ failureSelector = u.option(options.failTarget, $form.attr('up-fail-target'), function() {
1690
+ return u.createSelectorFromElement($form);
1691
+ });
1692
+ historyOption = u.option(options.history, $form.attr('up-history'), true);
1693
+ successTransition = u.option(options.transition, $form.attr('up-transition'));
1694
+ failureTransition = u.option(options.failTransition, $form.attr('up-fail-transition'));
1695
+ $form.addClass('up-active');
1696
+ request = {
1697
+ url: $form.attr('action') || up.browser.url(),
1698
+ type: ((_ref = $form.attr('method')) != null ? _ref.toUpperCase() : void 0) || 'POST',
1699
+ data: $form.serialize(),
1700
+ selector: successSelector
1701
+ };
1702
+ successUrl = function(xhr) {
1703
+ var redirectLocation, url;
1704
+ url = historyOption ? u.isString(historyOption) ? historyOption : (redirectLocation = xhr.getResponseHeader('X-Up-Previous-Redirect-Location')) ? redirectLocation : request.type === 'GET' ? request.url + '?' + request.data : void 0 : void 0;
1705
+ return u.option(url, false);
1706
+ };
1707
+ return u.ajax(request).always(function() {
1708
+ return $form.removeClass('up-active');
1709
+ }).done(function(html, textStatus, xhr) {
1710
+ return up.flow.implant(successSelector, html, {
1711
+ history: successUrl(xhr),
1712
+ transition: successTransition
1713
+ });
1714
+ }).fail(function(xhr, textStatus, errorThrown) {
1715
+ var html;
1716
+ html = xhr.responseText;
1717
+ return up.flow.implant(failureSelector, html, {
1718
+ transition: failureTransition
1719
+ });
1720
+ });
1721
+ };
1722
+
1723
+ /**
1724
+ Observes an input field by periodic polling its value.
1725
+ Executes code when the value changes.
1726
+
1727
+ up.observe('input', { change: function(value, $input) {
1728
+ up.submit($input)
1729
+ } });
1730
+
1731
+ This is useful for observing text fields while the user is typing,
1732
+ since browsers will only fire a `change` event once the user
1733
+ blurs the text field.
1734
+
1735
+ @method up.observe
1736
+ @param {Element|jQuery|String} fieldOrSelector
1737
+ @param {Function(value, $field)|String} options.change
1738
+ The callback to execute when the field's value changes.
1739
+ If given as a function, it must take two arguments (`value`, `$field`).
1740
+ If given as a string, it will be evaled as Javascript code in a context where
1741
+ (`value`, `$field`) are set.
1742
+ @param {Number} [options.frequency=500]
1743
+ */
1744
+ observe = function(fieldOrSelector, options) {
1745
+ var $field, callback, check, clearTimer, codeOnChange, knownValue, resetTimer, startTimer, timer;
1746
+ $field = $(fieldOrSelector);
1747
+ options = u.options(options, {
1748
+ frequency: 500
1749
+ });
1750
+ knownValue = null;
1751
+ timer = null;
1752
+ callback = null;
1753
+ if (codeOnChange = $field.attr('up-observe')) {
1754
+ callback = function(value, $field) {
1755
+ return eval(codeOnChange);
1756
+ };
1757
+ } else if (options.change) {
1758
+ callback = options.change;
1759
+ } else {
1760
+ u.error('observe: No change callback given');
1761
+ }
1762
+ check = function() {
1763
+ var skipCallback, value;
1764
+ value = $field.val();
1765
+ skipCallback = _.isNull(knownValue);
1766
+ if (knownValue !== value) {
1767
+ knownValue = value;
1768
+ if (!skipCallback) {
1769
+ return callback.apply($field.get(0), [value, $field]);
1770
+ }
1771
+ }
1772
+ };
1773
+ resetTimer = function() {
1774
+ if (timer) {
1775
+ clearTimer();
1776
+ return startTimer();
1777
+ }
1778
+ };
1779
+ clearTimer = function() {
1780
+ clearInterval(timer);
1781
+ return timer = null;
1782
+ };
1783
+ startTimer = function() {
1784
+ return timer = setInterval(check, options.frequency);
1785
+ };
1786
+ $field.bind("keyup click mousemove", resetTimer);
1787
+ check();
1788
+ startTimer();
1789
+ return clearTimer;
1790
+ };
1791
+
1792
+ /**
1793
+ Submits the form through AJAX, searches the response for the selector
1794
+ given in `up-target` and replaces the selector content in the current page:
1795
+
1796
+ <form method="POST" action="/users" up-target=".main">
1797
+ ...
1798
+ </form>
1799
+
1800
+ @method form[up-target]
1801
+ @ujs
1802
+ @param {String} up-target
1803
+ @param {String} [up-fail-target]
1804
+ @param {String} [up-history]
1805
+ @param {String} [up-transition]
1806
+ @param {String} [up-fail-transition]
1807
+ */
1808
+ up.on('submit', 'form[up-target]', function(event, $form) {
1809
+ event.preventDefault();
1810
+ return submit($form);
1811
+ });
1812
+
1813
+ /**
1814
+ Observes this form control by periodically polling its value.
1815
+ Executes the given Javascript if the value changes:
1816
+
1817
+ <form method="GET" action="/search">
1818
+ <input type="query" up-observe="up.form.submit(this)">
1819
+ </form>
1820
+
1821
+ This is useful for observing text fields while the user is typing,
1822
+ since browsers will only fire a `change` event once the user
1823
+ blurs the text field.
1824
+
1825
+ @method input[up-observe]
1826
+ @ujs
1827
+ @param {String} up-observe
1828
+ */
1829
+ up.awaken('[up-observe]', function($field) {
1830
+ return observe($field);
1831
+ });
1832
+ return {
1833
+ submit: submit,
1834
+ observe: observe
1835
+ };
1836
+ })();
1837
+
1838
+ up.submit = up.form.submit;
1839
+
1840
+ up.observe = up.form.observe;
1841
+
1842
+ }).call(this);
1843
+
1844
+ /**
1845
+ Pop-up overlays
1846
+ ===============
1847
+
1848
+ For modal dialogs see [up.modal](/up.modal).
1849
+
1850
+ @class up.popup
1851
+ */
1852
+
1853
+ (function() {
1854
+ up.popup = (function() {
1855
+ var autoclose, close, config, createHiddenPopup, defaults, ensureInViewport, open, position, source, u, updated;
1856
+ u = up.util;
1857
+ config = {
1858
+ openAnimation: 'fade-in',
1859
+ closeAnimation: 'fade-out',
1860
+ origin: 'bottom-right'
1861
+ };
1862
+
1863
+ /**
1864
+ @method up.popup.defaults
1865
+ @param {String} options.animation
1866
+ @param {String} options.origin
1867
+ */
1868
+ defaults = function(options) {
1869
+ return u.extend(config, options);
1870
+ };
1871
+ position = function($link, $popup, origin) {
1872
+ var css, linkBox;
1873
+ linkBox = u.measure($link, {
1874
+ full: true
1875
+ });
1876
+ css = (function() {
1877
+ switch (origin) {
1878
+ case "bottom-right":
1879
+ return {
1880
+ right: linkBox.right,
1881
+ top: linkBox.top + linkBox.height
1882
+ };
1883
+ case "bottom-left":
1884
+ return {
1885
+ left: linkBox.left,
1886
+ top: linkBox.bottom + linkBox.height
1887
+ };
1888
+ case "top-right":
1889
+ return {
1890
+ right: linkBox.right,
1891
+ bottom: linkBox.top
1892
+ };
1893
+ case "top-left":
1894
+ return {
1895
+ left: linkBox.left,
1896
+ bottom: linkBox.top
1897
+ };
1898
+ default:
1899
+ return u.error("Unknown origin", origin);
1900
+ }
1901
+ })();
1902
+ $popup.attr('up-origin', origin);
1903
+ $popup.css(css);
1904
+ return ensureInViewport($popup);
1905
+ };
1906
+ ensureInViewport = function($popup) {
1907
+ var bottom, box, errorX, errorY, left, right, top;
1908
+ box = u.measure($popup, {
1909
+ full: true
1910
+ });
1911
+ errorX = null;
1912
+ errorY = null;
1913
+ if (box.right < 0) {
1914
+ errorX = -box.right;
1915
+ }
1916
+ if (box.bottom < 0) {
1917
+ errorY = -box.bottom;
1918
+ }
1919
+ if (box.left < 0) {
1920
+ errorX = box.left;
1921
+ }
1922
+ if (box.top < 0) {
1923
+ errorY = box.top;
1924
+ }
1925
+ if (errorX) {
1926
+ if (left = parseInt($popup.css('left'))) {
1927
+ $popup.css('left', left - errorX);
1928
+ } else if (right = parseInt($popup.css('right'))) {
1929
+ $popup.css('right', right + errorX);
1930
+ }
1931
+ }
1932
+ if (errorY) {
1933
+ if (top = parseInt($popup.css('top'))) {
1934
+ return $popup.css('top', top - errorY);
1935
+ } else if (bottom = parseInt($popup.css('bottom'))) {
1936
+ return $popup.css('bottom', bottom + errorY);
1937
+ }
1938
+ }
1939
+ };
1940
+ createHiddenPopup = function($link, selector, sticky) {
1941
+ var $placeholder, $popup;
1942
+ $popup = u.$createElementFromSelector('.up-popup');
1943
+ if (sticky) {
1944
+ $popup.attr('up-sticky', '');
1945
+ }
1946
+ $popup.attr('up-previous-url', up.browser.url());
1947
+ $popup.attr('up-previous-title', document.title);
1948
+ $placeholder = u.$createElementFromSelector(selector);
1949
+ $placeholder.appendTo($popup);
1950
+ $popup.appendTo(document.body);
1951
+ $popup.hide();
1952
+ return $popup;
1953
+ };
1954
+ updated = function($link, $popup, origin, animation) {
1955
+ $popup.show();
1956
+ position($link, $popup, origin);
1957
+ return up.animate($popup, animation);
1958
+ };
1959
+
1960
+ /**
1961
+ Opens a popup overlay.
1962
+
1963
+ @method up.popup.open
1964
+ @param {Element|jQuery|String} elementOrSelector
1965
+ @param {String} [options.origin='bottom-right']
1966
+ @param {String} [options.animation]
1967
+ @param {Boolean} [options.sticky=false]
1968
+ If set to `true`, the popup remains
1969
+ open even if the page changes in the background.
1970
+ @param {Object} [options.history=false]
1971
+ */
1972
+ open = function(linkOrSelector, options) {
1973
+ var $link, $popup, animation, history, origin, selector, sticky, url;
1974
+ $link = $(linkOrSelector);
1975
+ options = u.options(options);
1976
+ url = u.option($link.attr('href'));
1977
+ selector = u.option(options.target, $link.attr('up-popup'), 'body');
1978
+ origin = u.option(options.origin, $link.attr('up-origin'), config.origin);
1979
+ animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
1980
+ sticky = u.option(options.sticky, $link.is('[up-sticky]'));
1981
+ history = u.option(options.history, $link.attr('up-history'), false);
1982
+ close();
1983
+ $popup = createHiddenPopup($link, selector, sticky);
1984
+ return up.replace(selector, url, {
1985
+ history: history,
1986
+ insert: function() {
1987
+ return updated($link, $popup, origin, animation);
1988
+ }
1989
+ });
1990
+ };
1991
+
1992
+ /**
1993
+ Returns the source URL for the fragment displayed
1994
+ in the current popup overlay, or `undefined` if no
1995
+ popup is open.
1996
+
1997
+ @method up.popup.source
1998
+ @return {String}
1999
+ the source URL
2000
+ */
2001
+ source = function() {
2002
+ var $popup;
2003
+ $popup = $('.up-popup');
2004
+ if (!$popup.is('.up-destroying')) {
2005
+ return $popup.find('[up-source]').attr('up-source');
2006
+ }
2007
+ };
2008
+
2009
+ /**
2010
+ Closes a currently opened popup overlay.
2011
+ Does nothing if no popup is currently open.
2012
+
2013
+ @method up.popup.close
2014
+ @param {Object} options
2015
+ See options for [`up.animate`](/up.motion#up.animate).
2016
+ */
2017
+ close = function(options) {
2018
+ var $popup;
2019
+ $popup = $('.up-popup');
2020
+ if ($popup.length) {
2021
+ options = u.options(options, {
2022
+ animation: config.closeAnimation,
2023
+ url: $popup.attr('up-previous-url'),
2024
+ title: $popup.attr('up-previous-title')
2025
+ });
2026
+ return up.destroy($popup, options);
2027
+ }
2028
+ };
2029
+ autoclose = function() {
2030
+ if (!$('.up-popup').is('[up-sticky]')) {
2031
+ return close();
2032
+ }
2033
+ };
2034
+
2035
+ /**
2036
+ Opens the target of this link in a popup overlay:
2037
+
2038
+ <a href="/decks" up-modal=".deck_list">Switch deck</a>
2039
+
2040
+ If the `up-sticky` attribute is set, the dialog does not auto-close
2041
+ if a page fragment below the popup overlay updates:
2042
+
2043
+ <a href="/decks" up-popup=".deck_list">Switch deck</a>
2044
+ <a href="/settings" up-popup=".options" up-sticky>Settings</a>
2045
+
2046
+ @method a[up-popup]
2047
+ @ujs
2048
+ @param up-target
2049
+ @param [up-sticky]
2050
+ @param [up-origin]
2051
+ */
2052
+ up.on('click', 'a[up-popup]', function(event, $link) {
2053
+ event.preventDefault();
2054
+ if ($link.is('.up-current')) {
2055
+ return close();
2056
+ } else {
2057
+ return open($link);
2058
+ }
2059
+ });
2060
+ up.on('click', 'body', function(event, $body) {
2061
+ var $target;
2062
+ $target = $(event.target);
2063
+ if (!($target.closest('.up-popup').length || $target.closest('[up-popup]').length)) {
2064
+ return close();
2065
+ }
2066
+ });
2067
+ up.bus.on('fragment:ready', function($fragment) {
2068
+ if (!$fragment.closest('.up-popup').length) {
2069
+ return autoclose();
2070
+ }
2071
+ });
2072
+ up.magic.onEscape(function() {
2073
+ return close();
2074
+ });
2075
+
2076
+ /**
2077
+ When an element with this attribute is clicked,
2078
+ a currently open popup is closed.
2079
+
2080
+ @method [up-close]
2081
+ @ujs
2082
+ */
2083
+ up.on('click', '[up-close]', function(event, $element) {
2084
+ if ($element.closest('.up-popup')) {
2085
+ return close();
2086
+ }
2087
+ });
2088
+ return {
2089
+ open: open,
2090
+ close: close,
2091
+ source: source,
2092
+ defaults: defaults
2093
+ };
2094
+ })();
2095
+
2096
+ }).call(this);
2097
+
2098
+ /**
2099
+ Modal dialogs
2100
+ =============
2101
+
2102
+ TODO: Write some documentation
2103
+
2104
+ @class up.modal
2105
+ */
2106
+
2107
+ (function() {
2108
+ up.modal = (function() {
2109
+ var autoclose, close, config, createHiddenModal, defaults, open, source, templateHtml, u, updated;
2110
+ u = up.util;
2111
+ config = {
2112
+ width: 'auto',
2113
+ height: 'auto',
2114
+ openAnimation: 'fade-in',
2115
+ closeAnimation: 'fade-out',
2116
+ closeLabel: 'X',
2117
+ template: function(config) {
2118
+ return "<div class=\"up-modal\">\n <div class=\"up-modal-dialog\">\n <div class=\"up-modal-close\" up-close>" + config.closeLabel + "</div>\n <div class=\"up-modal-content\"></div>\n </div>\n</div>";
2119
+ }
2120
+ };
2121
+
2122
+ /**
2123
+ @method up.modal.defaults
2124
+ @param {Number} options.width
2125
+ @param {Number} options.height
2126
+ @param {String|Function(config)} options.template
2127
+ @param {String} options.closeLabel
2128
+ @param {String} options.openAnimation
2129
+ @param {String} options.closeAnimation
2130
+ */
2131
+ defaults = function(options) {
2132
+ return u.extend(config, options);
2133
+ };
2134
+ templateHtml = function() {
2135
+ var template;
2136
+ template = config.template;
2137
+ if (u.isFunction(template)) {
2138
+ return template(config);
2139
+ } else {
2140
+ return template;
2141
+ }
2142
+ };
2143
+ createHiddenModal = function(selector, width, height, sticky) {
2144
+ var $content, $dialog, $modal, $placeholder;
2145
+ $modal = $(templateHtml());
2146
+ if (sticky) {
2147
+ $modal.attr('up-sticky', '');
2148
+ }
2149
+ $modal.attr('up-previous-url', up.browser.url());
2150
+ $modal.attr('up-previous-title', document.title);
2151
+ $dialog = $modal.find('.up-modal-dialog');
2152
+ if (u.isPresent(width)) {
2153
+ $dialog.css('width', width);
2154
+ }
2155
+ if (u.isPresent(height)) {
2156
+ $dialog.css('height', height);
2157
+ }
2158
+ $content = $dialog.find('.up-modal-content');
2159
+ $placeholder = u.$createElementFromSelector(selector);
2160
+ $placeholder.appendTo($content);
2161
+ $modal.appendTo(document.body);
2162
+ $modal.hide();
2163
+ return $modal;
2164
+ };
2165
+ updated = function($modal, animation) {
2166
+ $modal.show();
2167
+ return up.animate($modal, animation);
2168
+ };
2169
+
2170
+ /**
2171
+ Opens a modal overlay.
2172
+
2173
+ @method up.modal.open
2174
+ @param {Element|jQuery|String} elementOrSelector
2175
+ @param {Number} [options.width]
2176
+ @param {Number} [options.height]
2177
+ @param {String} [options.origin='bottom-right']
2178
+ @param {String} [options.animation]
2179
+ @param {Boolean} [options.sticky=false]
2180
+ If set to `true`, the modal remains
2181
+ open even if the page changes in the background.
2182
+ @param {Object} [options.history=true]
2183
+ */
2184
+ open = function(linkOrSelector, options) {
2185
+ var $link, $modal, animation, height, history, selector, sticky, url, width;
2186
+ $link = $(linkOrSelector);
2187
+ options = u.options(options);
2188
+ url = u.option($link.attr('href'));
2189
+ selector = u.option(options.target, $link.attr('up-modal'), 'body');
2190
+ width = u.option(options.width, $link.attr('up-width'), config.width);
2191
+ height = u.option(options.height, $link.attr('up-height'), config.height);
2192
+ animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
2193
+ sticky = u.option(options.sticky, $link.is('[up-sticky]'));
2194
+ history = u.option(options.history, $link.attr('up-history'), true);
2195
+ close();
2196
+ $modal = createHiddenModal(selector, width, height, sticky);
2197
+ return up.replace(selector, url, {
2198
+ history: history,
2199
+ insert: function() {
2200
+ return updated($modal, animation);
2201
+ }
2202
+ });
2203
+ };
2204
+
2205
+ /**
2206
+ Returns the source URL for the fragment displayed
2207
+ in the current modal overlay, or `undefined` if no
2208
+ modal is open.
2209
+
2210
+ @method up.modal.source
2211
+ @return {String}
2212
+ the source URL
2213
+ */
2214
+ source = function() {
2215
+ var $modal;
2216
+ $modal = $('.up-modal');
2217
+ if (!$modal.is('.up-destroying')) {
2218
+ return $modal.find('[up-source]').attr('up-source');
2219
+ }
2220
+ };
2221
+
2222
+ /**
2223
+ Closes a currently opened modal overlay.
2224
+ Does nothing if no modal is currently open.
2225
+
2226
+ @method up.modal.close
2227
+ @param {Object} options
2228
+ See options for [`up.animate`](/up.motion#up.animate)
2229
+ */
2230
+ close = function(options) {
2231
+ var $modal;
2232
+ $modal = $('.up-modal');
2233
+ if ($modal.length) {
2234
+ options = u.options(options, {
2235
+ animation: config.closeAnimation,
2236
+ url: $modal.attr('up-previous-url'),
2237
+ title: $modal.attr('up-previous-title')
2238
+ });
2239
+ return up.destroy($modal, options);
2240
+ }
2241
+ };
2242
+ autoclose = function() {
2243
+ if (!$('.up-modal').is('[up-sticky]')) {
2244
+ return close();
2245
+ }
2246
+ };
2247
+
2248
+ /**
2249
+ Opens the target of this link in a modal dialog:
2250
+
2251
+ <a href="/decks" up-modal=".deck_list">Switch deck</a>
2252
+
2253
+ If the `up-sticky` attribute is set, the dialog does not auto-close
2254
+ if a page fragment below the dialog updates:
2255
+
2256
+ <a href="/settings" up-modal=".options" up-sticky>Settings</a>
2257
+
2258
+ @method a[up-modal]
2259
+ @ujs
2260
+ @param up-target
2261
+ @param [up-sticky]
2262
+ */
2263
+ up.on('click', 'a[up-modal]', function(event, $link) {
2264
+ event.preventDefault();
2265
+ if ($link.is('.up-current')) {
2266
+ return close();
2267
+ } else {
2268
+ return open($link);
2269
+ }
2270
+ });
2271
+ up.on('click', 'body', function(event, $body) {
2272
+ var $target;
2273
+ $target = $(event.target);
2274
+ if (!($target.closest('.up-dialog').length || $target.closest('[up-modal]').length)) {
2275
+ return close();
2276
+ }
2277
+ });
2278
+ up.bus.on('fragment:ready', function($fragment) {
2279
+ if (!$fragment.closest('.up-modal').length) {
2280
+ return autoclose();
2281
+ }
2282
+ });
2283
+ up.magic.onEscape(function() {
2284
+ return close();
2285
+ });
2286
+
2287
+ /**
2288
+ When this element is clicked, closes a currently open dialog.
2289
+
2290
+ @method [up-close]
2291
+ @ujs
2292
+ */
2293
+ up.on('click', '[up-close]', function(event, $element) {
2294
+ if ($element.closest('.up-modal')) {
2295
+ return close();
2296
+ }
2297
+ });
2298
+ return {
2299
+ open: open,
2300
+ close: close,
2301
+ source: source,
2302
+ defaults: defaults
2303
+ };
2304
+ })();
2305
+
2306
+ }).call(this);
2307
+
2308
+ /**
2309
+ Tooltips
2310
+ ========
2311
+
2312
+ TODO: Write some documentation.
2313
+
2314
+ @class up.tooltip
2315
+ */
2316
+
2317
+ (function() {
2318
+ up.tooltip = (function() {
2319
+ var close, createElement, open, position, u;
2320
+ u = up.util;
2321
+ position = function($link, $tooltip, origin) {
2322
+ var css, linkBox, tooltipBox;
2323
+ linkBox = u.measure($link);
2324
+ tooltipBox = u.measure($tooltip);
2325
+ css = (function() {
2326
+ switch (origin) {
2327
+ case "top":
2328
+ return {
2329
+ left: linkBox.left + 0.5 * (linkBox.width - tooltipBox.width),
2330
+ top: linkBox.top - tooltipBox.height
2331
+ };
2332
+ case "bottom":
2333
+ return {
2334
+ left: linkBox.left + 0.5 * (linkBox.width - tooltipBox.width),
2335
+ top: linkBox.top + linkBox.height
2336
+ };
2337
+ default:
2338
+ return u.error("Unknown origin", origin);
2339
+ }
2340
+ })();
2341
+ $tooltip.attr('up-origin', origin);
2342
+ return $tooltip.css(css);
2343
+ };
2344
+ createElement = function(html) {
2345
+ return u.$createElementFromSelector('.up-tooltip').html(html).appendTo(document.body);
2346
+ };
2347
+
2348
+ /**
2349
+ Opens a tooltip.
2350
+
2351
+ @method up.tooltip.open
2352
+ @param {Element|jQuery|String} elementOrSelector
2353
+ @param {String} html
2354
+ @param {String} [options.origin='top']
2355
+ @param {String} [options.animation]
2356
+ */
2357
+ open = function(linkOrSelector, options) {
2358
+ var $link, $tooltip, animation, html, origin;
2359
+ if (options == null) {
2360
+ options = {};
2361
+ }
2362
+ $link = $(linkOrSelector);
2363
+ html = u.option(options.html, $link.attr('up-tooltip'));
2364
+ origin = u.option(options.origin, $link.attr('up-origin'), 'top');
2365
+ animation = u.option(options.animation, $link.attr('up-animation'), 'fade-in');
2366
+ close();
2367
+ $tooltip = createElement(html);
2368
+ position($link, $tooltip, origin);
2369
+ return up.animate($tooltip, animation, options);
2370
+ };
2371
+
2372
+ /**
2373
+ Closes a currently shown tooltip.
2374
+ Does nothing if no tooltip is currently shown.
2375
+
2376
+ @method up.tooltip.close
2377
+ @param {Object} options
2378
+ See options for See options for [`up.animate`](/up.motion#up.animate).
2379
+ */
2380
+ close = function(options) {
2381
+ var $tooltip;
2382
+ $tooltip = $('.up-tooltip');
2383
+ if ($tooltip.length) {
2384
+ options = u.options(options, {
2385
+ animation: 'fade-out'
2386
+ });
2387
+ return up.destroy($tooltip, options);
2388
+ }
2389
+ };
2390
+
2391
+ /**
2392
+ Displays a tooltip when hovering the mouse over this element:
2393
+
2394
+ <a href="/decks" up-tooltip="Show all decks">Decks</a>
2395
+
2396
+ @method [up-tooltip]
2397
+ @ujs
2398
+ */
2399
+ up.awaken('[up-tooltip]', function($link) {
2400
+ $link.on('mouseover', function() {
2401
+ return open($link);
2402
+ });
2403
+ return $link.on('mouseout', function() {
2404
+ return close();
2405
+ });
2406
+ });
2407
+ up.on('click', 'body', function(event, $body) {
2408
+ return close();
2409
+ });
2410
+ up.magic.onEscape(function() {
2411
+ return close();
2412
+ });
2413
+ return {
2414
+ open: open,
2415
+ close: close
2416
+ };
2417
+ })();
2418
+
2419
+ }).call(this);
2420
+
2421
+ /**
2422
+ Fast interaction feedback
2423
+ =========================
2424
+
2425
+ This module marks up link elements with classes indicating that
2426
+ they are currently loading (class `up-active`) or linking
2427
+ to the current location (class `up-current`).
2428
+
2429
+ This dramatically improves the perceived speed of your user interface
2430
+ by providing instant feedback for user interactions.
2431
+
2432
+ The classes are added and removed automatically whenever
2433
+ a page fragment is added, changed or destroyed through Up.js.
2434
+
2435
+ How Up.js computes the current location
2436
+ ---------------------------------------
2437
+
2438
+ From Up's point of view the "current" location is either:
2439
+
2440
+ - the URL displayed in the browser window's location bar
2441
+ - the source URL of a currently opened [modal dialog](/up.modal)
2442
+ - the source URL of a currently opened [popup overlay](/up.popup)
2443
+
2444
+ @class up.navigation
2445
+ */
2446
+
2447
+ (function() {
2448
+ up.navigation = (function() {
2449
+ var CLASS_ACTIVE, CLASS_CURRENT, SELECTOR_ACTIVE, SELECTOR_SECTION, enlargeClickArea, locationChanged, sectionClicked, unmarkActive;
2450
+ CLASS_ACTIVE = 'up-active';
2451
+ CLASS_CURRENT = 'up-current';
2452
+ SELECTOR_SECTION = 'a[href], a[up-target], [up-follow], [up-modal], [up-popup]';
2453
+ SELECTOR_ACTIVE = "." + CLASS_ACTIVE;
2454
+ locationChanged = function() {
2455
+ var modalLocation, popupLocation, windowLocation;
2456
+ windowLocation = up.util.normalizeUrl(up.browser.url(), {
2457
+ search: false
2458
+ });
2459
+ modalLocation = up.modal.source();
2460
+ popupLocation = up.popup.source();
2461
+ return up.util.each($(SELECTOR_SECTION), function(section) {
2462
+ var $section, url;
2463
+ $section = $(section);
2464
+ url = up.link.resolveUrl($section);
2465
+ url = up.util.normalizeUrl(url, {
2466
+ search: false
2467
+ });
2468
+ if (url === windowLocation || url === modalLocation || url === popupLocation) {
2469
+ return $section.addClass(CLASS_CURRENT);
2470
+ } else {
2471
+ return $section.removeClass(CLASS_CURRENT);
2472
+ }
2473
+ });
2474
+ };
2475
+ sectionClicked = function($section) {
2476
+ unmarkActive();
2477
+ $section = enlargeClickArea($section);
2478
+ return $section.addClass(CLASS_ACTIVE);
2479
+ };
2480
+ enlargeClickArea = function($section) {
2481
+ return up.util.presence($section.parents(SELECTOR_SECTION)) || $section;
2482
+ };
2483
+ unmarkActive = function() {
2484
+ return $(SELECTOR_ACTIVE).removeClass(CLASS_ACTIVE);
2485
+ };
2486
+ up.on('click', SELECTOR_SECTION, function(event, $section) {
2487
+ return sectionClicked($section);
2488
+ });
2489
+ up.bus.on('fragment:ready', function() {
2490
+ unmarkActive();
2491
+ return locationChanged();
2492
+ });
2493
+ return up.bus.on('fragment:destroy', function($fragment) {
2494
+ if ($fragment.is('.up-modal, .up-popup')) {
2495
+ return locationChanged();
2496
+ }
2497
+ });
2498
+ })();
2499
+
2500
+ }).call(this);
2501
+
2502
+ /**
2503
+ Markers
2504
+ =======
2505
+
2506
+ TODO: Write some documentation
2507
+
2508
+ @class up.marker
2509
+ */
2510
+
2511
+ (function() {
2512
+ up.marker = (function() {
2513
+ var check, hasContent;
2514
+ hasContent = function($marker) {
2515
+ return $marker.html().trim() !== '';
2516
+ };
2517
+ check = function($element) {
2518
+ return up.util.findWithSelf($element, '[up-marker]').each(function() {
2519
+ var $marker;
2520
+ $marker = $(this);
2521
+ if (!hasContent($marker)) {
2522
+ return $marker.hide();
2523
+ }
2524
+ });
2525
+ };
2526
+
2527
+ /**
2528
+ Use this attribute to mark up empty element containers that
2529
+ you plan to update with content in the future.
2530
+
2531
+ An element with this attribute is automatically hidden
2532
+ if it has no content, and is re-shown if it is updated with
2533
+ content.
2534
+
2535
+ This is useful to prevent the element from applying unwanted
2536
+ margins to the surrounding page flow.
2537
+
2538
+ @method [up-marker]
2539
+ @ujs
2540
+ */
2541
+ return up.bus.on('fragment:ready', check);
2542
+ })();
2543
+
2544
+ }).call(this);
2545
+ (function() {
2546
+ up.bus.emit('framework:ready');
2547
+
2548
+ $(document).on('ready', function() {
2549
+ return up.bus.emit('app:ready');
2550
+ });
2551
+
2552
+ }).call(this);