upjs-rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-version +2 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +47 -0
  6. data/Rakefile +1 -0
  7. data/bin/doc-server +3 -0
  8. data/bin/install-ydoc +4 -0
  9. data/design/animation-ghosting.txt +72 -0
  10. data/design/design.txt +34 -0
  11. data/design/draft.html.erb +48 -0
  12. data/design/draft.rb +9 -0
  13. data/lib/assets/javascripts/up/browser.js.coffee +20 -0
  14. data/lib/assets/javascripts/up/bus.js.coffee +54 -0
  15. data/lib/assets/javascripts/up/flow.js.coffee +160 -0
  16. data/lib/assets/javascripts/up/form.js.coffee +162 -0
  17. data/lib/assets/javascripts/up/history.js.coffee +33 -0
  18. data/lib/assets/javascripts/up/index.js +13 -0
  19. data/lib/assets/javascripts/up/link.js.coffee +95 -0
  20. data/lib/assets/javascripts/up/magic.js.coffee +79 -0
  21. data/lib/assets/javascripts/up/modal.js.coffee +51 -0
  22. data/lib/assets/javascripts/up/module.js.coffee +4 -0
  23. data/lib/assets/javascripts/up/motion.js.coffee +276 -0
  24. data/lib/assets/javascripts/up/navigation.js.coffee +63 -0
  25. data/lib/assets/javascripts/up/popup.js.coffee +143 -0
  26. data/lib/assets/javascripts/up/util.js.coffee +287 -0
  27. data/lib/assets/stylesheets/up/follow.css.sass +2 -0
  28. data/lib/assets/stylesheets/up/index.css +3 -0
  29. data/lib/assets/stylesheets/up/modal.css.sass +54 -0
  30. data/lib/assets/stylesheets/up/popup.css.sass +9 -0
  31. data/lib/upjs/rails/engine.rb +6 -0
  32. data/lib/upjs/rails/redirection.rb +26 -0
  33. data/lib/upjs/rails/request.rb +13 -0
  34. data/lib/upjs/rails/version.rb +5 -0
  35. data/lib/upjs-rails.rb +7 -0
  36. data/spec_app/.firefox-version +1 -0
  37. data/spec_app/.gitignore +17 -0
  38. data/spec_app/Gemfile +24 -0
  39. data/spec_app/Gemfile.lock +239 -0
  40. data/spec_app/README.rdoc +28 -0
  41. data/spec_app/Rakefile +6 -0
  42. data/spec_app/app/assets/images/.keep +0 -0
  43. data/spec_app/app/assets/javascripts/application.js +16 -0
  44. data/spec_app/app/assets/stylesheets/application.css +15 -0
  45. data/spec_app/app/assets/stylesheets/blocks/card.css.sass +11 -0
  46. data/spec_app/app/assets/stylesheets/blocks/controls.css.sass +7 -0
  47. data/spec_app/app/assets/stylesheets/blocks/field_with_errors.css.sass +5 -0
  48. data/spec_app/app/assets/stylesheets/blocks/menu.css.sass +13 -0
  49. data/spec_app/app/assets/stylesheets/blocks/panel.css.sass +8 -0
  50. data/spec_app/app/controllers/application_controller.rb +14 -0
  51. data/spec_app/app/controllers/cards_controller.rb +51 -0
  52. data/spec_app/app/controllers/concerns/.keep +0 -0
  53. data/spec_app/app/controllers/pages_controller.rb +6 -0
  54. data/spec_app/app/helpers/application_helper.rb +2 -0
  55. data/spec_app/app/mailers/.keep +0 -0
  56. data/spec_app/app/models/card.rb +6 -0
  57. data/spec_app/app/models/concerns/.keep +0 -0
  58. data/spec_app/app/models/tests.rb +27 -0
  59. data/spec_app/app/views/cards/_side.html.haml +4 -0
  60. data/spec_app/app/views/cards/index.html.haml +10 -0
  61. data/spec_app/app/views/cards/new.html.haml +15 -0
  62. data/spec_app/app/views/cards/show.html.haml +11 -0
  63. data/spec_app/app/views/layouts/application.html.erb +12 -0
  64. data/spec_app/app/views/pages/home.html.haml +5 -0
  65. data/spec_app/bin/bundle +3 -0
  66. data/spec_app/bin/rails +8 -0
  67. data/spec_app/bin/rake +8 -0
  68. data/spec_app/bin/setup +29 -0
  69. data/spec_app/bin/spring +18 -0
  70. data/spec_app/config/application.rb +26 -0
  71. data/spec_app/config/boot.rb +3 -0
  72. data/spec_app/config/cucumber.yml +8 -0
  73. data/spec_app/config/database.yml +25 -0
  74. data/spec_app/config/environment.rb +5 -0
  75. data/spec_app/config/environments/development.rb +41 -0
  76. data/spec_app/config/environments/production.rb +79 -0
  77. data/spec_app/config/environments/test.rb +42 -0
  78. data/spec_app/config/initializers/assets.rb +11 -0
  79. data/spec_app/config/initializers/backtrace_silencers.rb +7 -0
  80. data/spec_app/config/initializers/cookies_serializer.rb +3 -0
  81. data/spec_app/config/initializers/filter_parameter_logging.rb +4 -0
  82. data/spec_app/config/initializers/inflections.rb +16 -0
  83. data/spec_app/config/initializers/mime_types.rb +4 -0
  84. data/spec_app/config/initializers/session_store.rb +3 -0
  85. data/spec_app/config/initializers/wrap_parameters.rb +14 -0
  86. data/spec_app/config/locales/en.yml +23 -0
  87. data/spec_app/config/routes.rb +6 -0
  88. data/spec_app/config/secrets.yml +22 -0
  89. data/spec_app/config.ru +4 -0
  90. data/spec_app/db/migrate/20141225125143_create_card.rb +9 -0
  91. data/spec_app/db/schema.rb +23 -0
  92. data/spec_app/db/seeds.rb +7 -0
  93. data/spec_app/features/history.feature +30 -0
  94. data/spec_app/features/navigation.feature +9 -0
  95. data/spec_app/features/step_definitions/factory_steps.rb +5 -0
  96. data/spec_app/features/step_definitions/navigation_steps.rb +29 -0
  97. data/spec_app/features/step_definitions/utility_steps.rb +15 -0
  98. data/spec_app/features/support/env.rb +73 -0
  99. data/spec_app/features/support/find_by_anything.rb +19 -0
  100. data/spec_app/features/support/paths.rb +51 -0
  101. data/spec_app/lib/assets/.keep +0 -0
  102. data/spec_app/lib/tasks/.keep +0 -0
  103. data/spec_app/lib/tasks/cucumber.rake +65 -0
  104. data/spec_app/log/.keep +0 -0
  105. data/spec_app/public/404.html +67 -0
  106. data/spec_app/public/422.html +67 -0
  107. data/spec_app/public/500.html +66 -0
  108. data/spec_app/public/favicon.ico +0 -0
  109. data/spec_app/public/robots.txt +5 -0
  110. data/spec_app/script/cucumber +10 -0
  111. data/spec_app/test/controllers/.keep +0 -0
  112. data/spec_app/test/fixtures/.keep +0 -0
  113. data/spec_app/test/helpers/.keep +0 -0
  114. data/spec_app/test/integration/.keep +0 -0
  115. data/spec_app/test/mailers/.keep +0 -0
  116. data/spec_app/test/models/.keep +0 -0
  117. data/spec_app/test/test_helper.rb +10 -0
  118. data/spec_app/vendor/assets/javascripts/.keep +0 -0
  119. data/spec_app/vendor/assets/stylesheets/.keep +0 -0
  120. data/upjs-rails.gemspec +24 -0
  121. metadata +207 -0
@@ -0,0 +1,33 @@
1
+ up.history = (->
2
+
3
+ replace = (url) ->
4
+ manipulate "replace", url
5
+
6
+ push = (url) ->
7
+ manipulate "push", url
8
+
9
+ manipulate = (method, url) ->
10
+ method += "State" # resulting in either pushState or replaceState
11
+ window.history[method]({ fromUp: true }, '', url)
12
+
13
+ pop = (event) ->
14
+ state = event.originalEvent.state
15
+ console.log "popping state", state
16
+ console.log "current href", currentUrl()
17
+ if state?.fromUp
18
+ up.visit currentUrl(), history: { method: 'replace' }
19
+ else
20
+ console.log "null state"
21
+
22
+ currentUrl = ->
23
+ location.href
24
+
25
+ setTimeout (->
26
+ $(window).on "popstate", pop
27
+ replace(currentUrl())
28
+ ), 200
29
+
30
+ push: push
31
+ replace: replace
32
+
33
+ )()
@@ -0,0 +1,13 @@
1
+ //= require up/module
2
+ //= require up/util
3
+ //= require up/browser
4
+ //= require up/bus
5
+ //= require up/flow
6
+ //= require up/magic
7
+ //= require up/history
8
+ //= require up/motion
9
+ //= require up/link
10
+ //= require up/form
11
+ //= require up/popup
12
+ //= require up/modal
13
+ //= require up/navigation
@@ -0,0 +1,95 @@
1
+ ###*
2
+ Links.
3
+
4
+ @class up.link
5
+ ###
6
+
7
+ up.link = (->
8
+
9
+ ###*
10
+ Visits the given URL without a full page load.
11
+ This is done by fetching `url` through an AJAX request
12
+ and replaceing the current `<body>` tag with the response's `<body>` tag..
13
+
14
+ @method up.visit
15
+ @param {String} url
16
+ The URL to visit.
17
+ @param {Object} options
18
+ See options for {{#crossLink "up.flow/up.replace"}}{{/crossLink}}.
19
+ @example
20
+ <a href="/users" up-follow>User list</a>
21
+ ###
22
+ visit = (url, options) ->
23
+ console.log("up.visit", url)
24
+ # options = up.util.options(options, )
25
+ up.replace('body', url, options)
26
+
27
+ ###*
28
+ Follows the given link and replaces a selector in the current page
29
+ with corresponding elements from a new page fetched from the server.
30
+
31
+ @method up.follow
32
+ @param {Element|jQuery|String} link
33
+ An element or selector which resolves to an `<a>` tag
34
+ or any element that is marked up with an `up-follow` attribute.
35
+ @param {String} [options.target]
36
+ The selector to replace.
37
+ Defaults to the `up-target` attribute on `link`,
38
+ or to `body` if such an attribute does not exist.
39
+ @param {Function|String} [options.transition]
40
+ A transition function or name.
41
+ @example
42
+ <a href="/users" up-target=".main">User list</a>
43
+ ###
44
+ follow = (link, options) ->
45
+ $link = $(link)
46
+ options = up.util.options(options)
47
+ url = up.util.presentAttr($link, 'href', 'up-follow')
48
+ selector = options.target || $link.attr("up-target") || 'body'
49
+ options.transition ||= $link.attr('up-transition')
50
+ up.replace(selector, url, options)
51
+
52
+ resolve = (element) ->
53
+ $element = $(element)
54
+ if $element.is('a') || up.util.presentAttr($element, 'up-follow')
55
+ $element
56
+ else
57
+ $element.find('a:first')
58
+
59
+ resolveUrl = (element) ->
60
+ if link = resolve(element)
61
+ up.util.presentAttr(link, 'href', 'up-follow')
62
+
63
+ markActive = (element) ->
64
+ markUnactive()
65
+ $element = $(element)
66
+ $clickArea = $element.ancestors('up-follow')
67
+ $clickArea = $element unless $clickArea.length
68
+ $clickArea.addClass('up-active')
69
+
70
+ markUnactive = ->
71
+ $('[up-active]').removeClass('up-active')
72
+
73
+ up.on 'click', 'a[up-target]', (event, $link) ->
74
+ event.preventDefault()
75
+ follow($link)
76
+
77
+ up.on 'click', '[up-follow]', (event, $element) ->
78
+
79
+ childLinkClicked = ->
80
+ $target = $(event.target)
81
+ $target.closest('a').length && $element.has($target).length
82
+
83
+ unless childLinkClicked()
84
+ event.preventDefault()
85
+ follow(resolve($element))
86
+
87
+ visit: visit
88
+ follow: follow
89
+ resolve: resolve
90
+ resolveUrl: resolveUrl
91
+
92
+ )()
93
+
94
+ up.visit = up.link.visit
95
+ up.follow = up.link.follow
@@ -0,0 +1,79 @@
1
+ ###*
2
+ Event handling.
3
+
4
+ @class up.magic
5
+ ###
6
+ up.magic = (->
7
+
8
+ AWAKENED_CLASS = 'up-awakened'
9
+ DESTROYER_KEY = 'up-destroyer'
10
+
11
+ ###*
12
+ Binds an event handler to the document,
13
+ which will be executed whenever the given event
14
+ is triggered on the given selector.
15
+
16
+ @method up.on
17
+ @param {String} events
18
+ A space-separated list of event names to bind.
19
+ @param {String} selector
20
+ The selector an on which the event must be triggered.
21
+ @param {Function} behavior
22
+ The handler that should be called.
23
+ ###
24
+ live = (events, selector, behavior) ->
25
+ $(document).on events, selector, (event) ->
26
+ behavior.apply(this, [event, $(this)])
27
+
28
+ awakeners = []
29
+
30
+ ###*
31
+ Registers a function to be called whenever an element with
32
+ the given selector is inserted into the DOM through Up.js.
33
+
34
+ @method up.awaken
35
+ @param {String} selector
36
+ The selector to match.
37
+ @param {Function} awakener
38
+ The function to call when a matching element is inserted.
39
+ The function takes the new element as the first argument (as a jQuery object).
40
+ It may return another function that destroys the awakened
41
+ object when it is removed from the DOM, by clearing global state such as
42
+ time-outs and event handlers bound to the document.
43
+ ###
44
+ awaken = (selector, awakener) ->
45
+ awakeners.push
46
+ selector: selector
47
+ behavior: awakener
48
+
49
+ $deepFilter = ($element, selector) ->
50
+ $element.find(selector).addBack(selector)
51
+
52
+ compile = ($fragment) ->
53
+ for awakener in awakeners
54
+ $deepFilter($fragment, awakener.selector).each ->
55
+ $element = $(this)
56
+ destroyer = awakener.behavior.apply(this, [$element])
57
+ if up.util.isFunction(destroyer)
58
+ $element.prop(AWAKENED_CLASS, true)
59
+ $element.data(DESTROYER_KEY, destroyer)
60
+
61
+ destroy = ($fragment) ->
62
+ $deepFilter($fragment, "[#{AWAKENED_CLASS}]").each ->
63
+ $element = $(this)
64
+ destroyer = $element.data(DESTROYER_KEY)
65
+ destroyer()
66
+
67
+ up.bus.on 'app:ready', (-> up.bus.emit 'fragment:ready', $(document.body))
68
+ up.bus.on 'fragment:ready', compile
69
+ up.bus.on 'fragment:destroy', destroy
70
+ $(document).on 'ready', -> up.bus.emit('app:ready')
71
+
72
+ awaken: awaken
73
+ on: live
74
+
75
+ )()
76
+
77
+ up.awaken = up.magic.awaken
78
+ up.on = up.magic.on
79
+
@@ -0,0 +1,51 @@
1
+ ###*
2
+ Modal dialogs (WIP).
3
+
4
+ @class up.modal
5
+ ###
6
+ up.modal = (->
7
+
8
+ # configuration =
9
+ # width: 600
10
+ # height: 400
11
+ # template:
12
+ # """
13
+ # <div class="up-modal">
14
+ # <div class="up-modal-overlay"></div>
15
+ # <div class="up-modal-dialog">
16
+ # <a href="#" class="up-modal-close">
17
+ # <span class="up-modal-close-label">Close</span>
18
+ # <span class="up-modal-close-key">ESC</span>
19
+ # </a>
20
+ # <div class="up-modal-content"></div>
21
+ # </div>
22
+ # </div>
23
+ # """
24
+ #
25
+ # defaults = (defaults) ->
26
+ # up.util.extend(configuration, defaults)
27
+ #
28
+ # open = (link, options) ->
29
+ # $link = $(link)
30
+ # url = $link.attr("href")
31
+ # selector = $link.attr("up-modal") || $link.attr("up-target") || 'body'
32
+ # options.source = true
33
+ # replace(selector, url, options)
34
+ # options = up.util.options(options, configuration)
35
+ # createElements()
36
+ # update(options)
37
+ #
38
+ # close = ->
39
+ # if $container
40
+ # $container.remove()
41
+ # $container = null
42
+
43
+ source = ->
44
+ $('.up-modal').find('[up-source]').attr('up-source')
45
+
46
+ # defaults: defaults
47
+ # open: open
48
+ # close: close
49
+ source: source
50
+
51
+ )()
@@ -0,0 +1,4 @@
1
+ ###*
2
+ @module up
3
+ ###
4
+ window.up = {}
@@ -0,0 +1,276 @@
1
+ ###*
2
+ Animation and transition effects.
3
+
4
+ @class up.motion
5
+ ###
6
+ up.motion = (->
7
+
8
+ defaultOptions =
9
+ duration: 300
10
+ easing: 'ease'
11
+
12
+ animations = {}
13
+ transitions = {}
14
+
15
+ cssAnimate = up.util.cssAnimate
16
+
17
+ ###*
18
+ Animates an element.
19
+
20
+ The following animations are pre-registered:
21
+
22
+ - `fade-in`
23
+ - `fade-out`
24
+ - `move-to-top`
25
+ - `move-from-top`
26
+ - `move-to-bottom`
27
+ - `move-from-bottom`
28
+ - `move-to-left`
29
+ - `move-from-left`
30
+ - `move-to-right`
31
+ - `move-from-right`
32
+ - `none`
33
+
34
+ @method up.animate
35
+ @param {Element|jQuery|String} elementOrSelector
36
+ @param {String|Function} animationOrName
37
+ @param {Number} [options.duration]
38
+ @param {String} [options.easing]
39
+ @return {Promise}
40
+ A promise for the animation's end.
41
+ ###
42
+ animate = (elementOrSelector, animationOrName, options) ->
43
+ $element = $(elementOrSelector)
44
+ console.log("animating with", animationOrName)
45
+ options = up.util.options(options, defaultOptions)
46
+ anim = if up.util.isFunction(animationOrName)
47
+ animationOrName
48
+ else
49
+ animations[animationOrName] or up.util.error("Unknown animation", animationName)
50
+ assertIsPromise(
51
+ anim($element, options),
52
+ ["Animation did not return a Promise", animationOrName]
53
+ )
54
+
55
+ withGhosts = ($old, $new, block) ->
56
+ $oldGhost = null
57
+ $newGhost = null
58
+ up.util.temporaryCss $new, display: 'none', ->
59
+ $oldGhost = up.util.prependGhost($old)
60
+ up.util.temporaryCss $old, display: 'none', ->
61
+ $newGhost = up.util.prependGhost($new)
62
+ # $old should take up space in the page flow until the transition ends
63
+ $old.css(visibility: 'hidden')
64
+ newCssMemo = up.util.temporaryCss($new, display: 'none')
65
+ promise = block($oldGhost, $newGhost)
66
+ promise.then ->
67
+ $oldGhost.remove()
68
+ $newGhost.remove()
69
+ # Now that the transition is over we show $new again.
70
+ # Since we expect $old to be removed in a heartblink,
71
+ # $new should take up space
72
+ $old.css(display: 'none')
73
+ newCssMemo()
74
+
75
+ assertIsPromise = (object, messageParts) ->
76
+ up.util.isPromise(object) or up.util.error(messageParts...)
77
+ object
78
+
79
+
80
+
81
+
82
+ ###*
83
+ Performs a transition between two elements.
84
+
85
+ The following transitions are pre-registered:
86
+
87
+ - `cross-fade`
88
+ - `move-top`
89
+ - `move-bottom`
90
+ - `move-left`
91
+ - `move-right`
92
+ - `none`
93
+
94
+ You can also compose a transition from two animation names
95
+ separated by a slash character (`/`):
96
+
97
+ - `move-to-bottom/fade-in`
98
+ - `move-to-left/move-from-top`
99
+
100
+ @method up.morph
101
+ @param {Element|jQuery|String} source
102
+ @param {Element|jQuery|String} target
103
+ @param {Function|String} transitionOrName
104
+ @param {Number} [options.duration]
105
+ @param {String} [options.easing]
106
+ @return {Promise}
107
+ A promise for the transition's end.
108
+ ###
109
+ morph = (source, target, transitionOrName, options) ->
110
+ options = up.util.options(defaultOptions)
111
+ $old = $(source)
112
+ $new = $(target)
113
+ transition = up.util.presence(transitionOrName, up.util.isFunction) || transitions[transitionOrName]
114
+ if transition
115
+ withGhosts $old, $new, ($oldGhost, $newGhost) ->
116
+ assertIsPromise(
117
+ transition($oldGhost, $newGhost, options),
118
+ ["Transition did not return a promise", transitionOrName]
119
+ )
120
+ else if animation = animations[transitionOrName]
121
+ $old.hide()
122
+ animate($new, animation, options)
123
+ else if up.util.isString(transitionOrName) && transitionOrName.indexOf('/') >= 0
124
+ parts = transitionOrName.split('/')
125
+ transition = ($old, $new, options) ->
126
+ $.when(
127
+ animate($old, parts[0], options),
128
+ animate($new, parts[1], options)
129
+ )
130
+ morph($old, $new, transition, options)
131
+ else
132
+ up.util.error("Unknown transition: #{transitionOrName}")
133
+
134
+ ###*
135
+ Defines a named transition.
136
+
137
+ @method up.transition
138
+ @param {String} name
139
+ @param {Function} transition
140
+ ###
141
+ transition = (name, transition) ->
142
+ transitions[name] = transition
143
+
144
+ ###*
145
+ Defines a named animation.
146
+
147
+ @method up.animation
148
+ @param {String} name
149
+ @param {Function} animation
150
+ ###
151
+ animation = (name, animation) ->
152
+ animations[name] = animation
153
+
154
+ ###*
155
+ Returns a no-op animation or transition which has no visual effects
156
+ and completes instantly.
157
+
158
+ @method up.motion.none
159
+ @return {Promise}
160
+ A resolved promise
161
+ ###
162
+ none = ->
163
+ deferred = $.Deferred()
164
+ deferred.resolve()
165
+ deferred.promise()
166
+
167
+ animation('none', none)
168
+
169
+ animation('fade-in', ($ghost, options) ->
170
+ $ghost.css(opacity: 0)
171
+ cssAnimate($ghost, { opacity: 1 }, options)
172
+ )
173
+
174
+ animation('fade-out', ($ghost, options) ->
175
+ $ghost.css(opacity: 1)
176
+ cssAnimate($ghost, { opacity: 0 }, options)
177
+ )
178
+
179
+ animation('move-to-top', ($ghost, options) ->
180
+ $ghost.css('margin-top': '0%')
181
+ cssAnimate($ghost, { 'margin-top': '-100%' }, options)
182
+ )
183
+
184
+ animation('move-from-top', ($ghost, options) ->
185
+ $ghost.css('margin-top': '-100%')
186
+ cssAnimate($ghost, { 'margin-top': '0%' }, options)
187
+ )
188
+
189
+ animation('move-to-bottom', ($ghost, options) ->
190
+ $ghost.css('margin-top': '0%')
191
+ cssAnimate($ghost, { 'margin-top': '100%' }, options)
192
+ )
193
+
194
+ animation('move-from-bottom', ($ghost, options) ->
195
+ $ghost.css('margin-top': '100%')
196
+ cssAnimate($ghost, { 'margin-top': '0%' }, options)
197
+ )
198
+
199
+ animation('move-to-left', ($ghost, options) ->
200
+ $ghost.css('margin-left': '0%')
201
+ cssAnimate($ghost, { 'margin-left': '-100%' }, options)
202
+ )
203
+
204
+ animation('move-from-left', ($ghost, options) ->
205
+ $ghost.css('margin-left': '-100%')
206
+ cssAnimate($ghost, { 'margin-left': '0%' }, options)
207
+ )
208
+
209
+ animation('move-to-right', ($ghost, options) ->
210
+ $ghost.css('margin-left': '0%')
211
+ cssAnimate($ghost, { 'margin-left': '100%' }, options)
212
+ )
213
+
214
+ animation('move-from-right', ($ghost, options) ->
215
+ $ghost.css('margin-left': '100%')
216
+ cssAnimate($ghost, { 'margin-left': '0%' }, options)
217
+ )
218
+
219
+ animation('roll-down', ($ghost, options) ->
220
+ fullHeight = $ghost.height()
221
+ styleMemo = up.util.temporaryCss($ghost,
222
+ height: '0px'
223
+ overflow: 'hidden'
224
+ )
225
+ cssAnimate($ghost, { height: "#{fullHeight}px" }, options).then(styleMemo)
226
+ )
227
+
228
+ transition('none', none)
229
+
230
+ transition('move-left', ($old, $new, options) ->
231
+ $.when(
232
+ animate($old, 'move-to-left', options),
233
+ animate($new, 'move-from-right', options)
234
+ )
235
+ )
236
+
237
+ transition('move-right', ($old, $new, options) ->
238
+ $.when(
239
+ animate($old, 'move-to-right', options),
240
+ animate($new, 'move-from-left', options)
241
+ )
242
+ )
243
+
244
+ transition('move-top', ($old, $new, options) ->
245
+ $.when(
246
+ animate($old, 'move-to-top', options),
247
+ animate($new, 'move-from-bottom', options)
248
+ )
249
+ )
250
+
251
+ transition('move-bottom', ($old, $new, options) ->
252
+ $.when(
253
+ animate($old, 'move-to-bottom', options),
254
+ animate($new, 'move-from-top', options)
255
+ )
256
+ )
257
+
258
+ transition('cross-fade', ($old, $new, options) ->
259
+ $.when(
260
+ animate($old, 'fade-out', options),
261
+ animate($new, 'fade-in', options)
262
+ )
263
+ )
264
+
265
+ morph: morph
266
+ animate: animate
267
+ transition: transition
268
+ animation: animation
269
+ none: none
270
+
271
+ )()
272
+
273
+ up.transition = up.motion.transition
274
+ up.animation = up.motion.animation
275
+ up.morph = up.motion.morph
276
+ up.animate = up.motion.animate
@@ -0,0 +1,63 @@
1
+ ###*
2
+ This module marks up link elements with classes indicating that
3
+ they are currently loading (class `up-active`) or linking
4
+ to the current location (class `up-current`).
5
+
6
+ The current location is either:
7
+
8
+ - the URL displayed in the browser window's location bar
9
+ - the source URL of a currently opened {{#crossLink "up.modal"}}modal dialog{{/crossLink}}
10
+ - the source URL of a currently opened {{#crossLink "up.popup"}}popup overlay{{/crossLink}}
11
+
12
+ @class up.navigation
13
+ ###
14
+ up.navigation = (->
15
+
16
+ CLASS_ACTIVE = 'up-active'
17
+ CLASS_CURRENT = 'up-current'
18
+ SELECTOR_SECTION = 'a[href], a[up-target], [up-follow], [up-modal], [up-popup]'
19
+ SELECTOR_ACTIVE = ".#{CLASS_ACTIVE}"
20
+
21
+ locationChanged = ->
22
+ windowLocation = up.util.normalizeUrl(location.href, search: false)
23
+ modalLocation = up.modal.source()
24
+ popupLocation = up.popup.source()
25
+
26
+ up.util.each $(SELECTOR_SECTION), (section) ->
27
+ $section = $(section)
28
+ # if $section is marked up with up-follow,
29
+ # the actual link might be a child element.
30
+ url = up.link.resolveUrl($section)
31
+ url = up.util.normalizeUrl(url, search: false)
32
+ if url == windowLocation || url == modalLocation || url == popupLocation
33
+ $section.addClass(CLASS_CURRENT)
34
+ else
35
+ $section.removeClass(CLASS_CURRENT)
36
+
37
+ sectionClicked = ($section) ->
38
+ unmarkActive()
39
+ $section = enlargeClickArea($section)
40
+ $section.addClass(CLASS_ACTIVE)
41
+
42
+ enlargeClickArea = ($section) ->
43
+ up.util.presence($section.parents(SELECTOR_SECTION)) || $section
44
+
45
+ unmarkActive = ->
46
+ $(SELECTOR_ACTIVE).removeClass(CLASS_ACTIVE)
47
+
48
+ up.on 'click', SELECTOR_SECTION, (event, $section) ->
49
+ sectionClicked($section)
50
+
51
+ # If a new fragment is inserted, it's likely to be the result
52
+ # to the active action. So we can remove the active marker.
53
+ up.bus.on 'fragment:ready', ->
54
+ unmarkActive()
55
+ locationChanged()
56
+
57
+ # If the destroyed fragment is a modal or popup container
58
+ # this changes which URLs we consider currents.
59
+ up.bus.on 'fragment:destroy', ($fragment) ->
60
+ if $fragment.is('.up-modal, .up-popup')
61
+ locationChanged()
62
+
63
+ )()