unpoly-rails 0.57.0 → 0.60.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +393 -1
  3. data/Gemfile.lock +5 -2
  4. data/README.md +1 -1
  5. data/README_RAILS.md +1 -1
  6. data/Rakefile +10 -1
  7. data/design/es6.js +32 -0
  8. data/design/ie11.txt +9 -0
  9. data/design/measure_jquery/element_list.js +41 -0
  10. data/design/measure_jquery/up.on_vs_addEventListener.js +56 -0
  11. data/design/todo_jquery.txt +13 -0
  12. data/dist/unpoly-bootstrap3.js +8 -8
  13. data/dist/unpoly-bootstrap3.min.js +1 -1
  14. data/dist/unpoly.css +22 -20
  15. data/dist/unpoly.js +6990 -5336
  16. data/dist/unpoly.min.css +1 -1
  17. data/dist/unpoly.min.js +4 -4
  18. data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +5 -0
  19. data/lib/assets/javascripts/unpoly.coffee +8 -6
  20. data/lib/assets/javascripts/unpoly/browser.coffee.erb +23 -118
  21. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +36 -0
  22. data/lib/assets/javascripts/unpoly/classes/cache.coffee +4 -4
  23. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +45 -39
  24. data/lib/assets/javascripts/unpoly/classes/config.coffee +9 -0
  25. data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +18 -27
  26. data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +39 -0
  27. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +116 -0
  28. data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +8 -8
  29. data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +19 -19
  30. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +54 -31
  31. data/lib/assets/javascripts/unpoly/classes/{focus_tracker.coffee → focus_follower.coffee} +2 -2
  32. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +25 -25
  33. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +4 -11
  34. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +157 -0
  35. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +525 -0
  36. data/lib/assets/javascripts/unpoly/classes/record.coffee +8 -2
  37. data/lib/assets/javascripts/unpoly/classes/rect.js +21 -0
  38. data/lib/assets/javascripts/unpoly/classes/request.coffee +41 -35
  39. data/lib/assets/javascripts/unpoly/classes/response.coffee +7 -3
  40. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +102 -0
  41. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +67 -0
  42. data/lib/assets/javascripts/unpoly/classes/selector.coffee +60 -0
  43. data/lib/assets/javascripts/unpoly/classes/tether.coffee +105 -0
  44. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +12 -7
  45. data/lib/assets/javascripts/unpoly/element.coffee.erb +1126 -0
  46. data/lib/assets/javascripts/unpoly/event.coffee.erb +437 -0
  47. data/lib/assets/javascripts/unpoly/feedback.coffee +73 -94
  48. data/lib/assets/javascripts/unpoly/form.coffee.erb +188 -181
  49. data/lib/assets/javascripts/unpoly/{dom.coffee.erb → fragment.coffee.erb} +250 -283
  50. data/lib/assets/javascripts/unpoly/framework.coffee +67 -0
  51. data/lib/assets/javascripts/unpoly/history.coffee +29 -28
  52. data/lib/assets/javascripts/unpoly/legacy.coffee +60 -0
  53. data/lib/assets/javascripts/unpoly/link.coffee.erb +127 -119
  54. data/lib/assets/javascripts/unpoly/log.coffee +99 -19
  55. data/lib/assets/javascripts/unpoly/modal.coffee.erb +95 -118
  56. data/lib/assets/javascripts/unpoly/motion.coffee.erb +158 -138
  57. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  58. data/lib/assets/javascripts/unpoly/popup.coffee.erb +119 -102
  59. data/lib/assets/javascripts/unpoly/protocol.coffee +11 -15
  60. data/lib/assets/javascripts/unpoly/proxy.coffee +62 -65
  61. data/lib/assets/javascripts/unpoly/radio.coffee +3 -5
  62. data/lib/assets/javascripts/unpoly/rails.coffee +8 -9
  63. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +173 -125
  64. data/lib/assets/javascripts/unpoly/toast.coffee +25 -24
  65. data/lib/assets/javascripts/unpoly/tooltip.coffee +89 -79
  66. data/lib/assets/javascripts/unpoly/util.coffee.erb +579 -1074
  67. data/lib/assets/javascripts/unpoly/{layout.coffee.erb → viewport.coffee.erb} +334 -264
  68. data/lib/assets/stylesheets/unpoly/dom.sass +1 -1
  69. data/lib/assets/stylesheets/unpoly/layout.sass +2 -0
  70. data/lib/assets/stylesheets/unpoly/popup.sass +0 -1
  71. data/lib/assets/stylesheets/unpoly/tooltip.sass +17 -12
  72. data/lib/unpoly/rails/version.rb +1 -1
  73. data/package.json +1 -2
  74. data/spec_app/Gemfile +2 -1
  75. data/spec_app/Gemfile.lock +38 -27
  76. data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
  77. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -2
  78. data/spec_app/app/assets/stylesheets/integration_test.sass +14 -1
  79. data/spec_app/app/controllers/scroll_test_controller.rb +5 -0
  80. data/spec_app/app/views/css_test/modal.erb +6 -6
  81. data/spec_app/app/views/css_test/popup.erb +44 -18
  82. data/spec_app/app/views/css_test/tooltip.erb +23 -4
  83. data/spec_app/app/views/error_test/trigger.erb +1 -1
  84. data/spec_app/app/views/form_test/basics/new.erb +1 -3
  85. data/spec_app/app/views/pages/start.erb +9 -2
  86. data/spec_app/app/views/reveal_test/long1.erb +1 -1
  87. data/spec_app/app/views/reveal_test/long2.erb +1 -1
  88. data/spec_app/app/views/reveal_test/within_document_viewport.erb +24 -0
  89. data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +28 -0
  90. data/spec_app/app/views/scroll_test/long1.erb +30 -0
  91. data/spec_app/config/routes.rb +1 -0
  92. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +3 -0
  93. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +1 -0
  94. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +17 -5
  95. data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +1 -1
  96. data/spec_app/spec/javascripts/helpers/fixture.js.coffee +25 -0
  97. data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +1 -0
  98. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -0
  99. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +1 -1
  100. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +2 -2
  101. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +4 -1
  102. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +3 -0
  103. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +2 -1
  104. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +2 -2
  105. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +18 -11
  106. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +3 -0
  107. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +3 -0
  108. data/spec_app/spec/javascripts/helpers/spec_util.coffee +47 -0
  109. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +3 -0
  110. data/spec_app/spec/javascripts/helpers/to_be_array.coffee +5 -0
  111. data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +6 -2
  112. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +3 -0
  113. data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +6 -2
  114. data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +8 -0
  115. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +3 -0
  116. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +3 -0
  117. data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +8 -0
  118. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +3 -0
  119. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +3 -0
  120. data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +3 -0
  121. data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +9 -0
  122. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +3 -0
  123. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +3 -0
  124. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +1 -2
  125. data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +7 -0
  126. data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +7 -0
  127. data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +10 -0
  128. data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +10 -0
  129. data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +8 -0
  130. data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +7 -3
  131. data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +3 -0
  132. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +1 -0
  133. data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +9 -0
  134. data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -21
  135. data/spec_app/spec/javascripts/helpers/to_match_list.coffee +14 -0
  136. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +3 -0
  137. data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +4 -1
  138. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +1 -0
  139. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +91 -7
  140. data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +3 -0
  141. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +23 -90
  142. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +3 -0
  143. data/spec_app/spec/javascripts/up/classes/config_spec.coffee +24 -0
  144. data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +45 -0
  145. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +5 -2
  146. data/spec_app/spec/javascripts/up/classes/params_spec.coffee +557 -0
  147. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +7 -4
  148. data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +51 -0
  149. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +3 -0
  150. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +3 -2
  151. data/spec_app/spec/javascripts/up/element_spec.coffee +897 -0
  152. data/spec_app/spec/javascripts/up/event_spec.js.coffee +496 -0
  153. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +69 -48
  154. data/spec_app/spec/javascripts/up/form_spec.js.coffee +252 -194
  155. data/spec_app/spec/javascripts/up/{dom_spec.js.coffee → fragment_spec.js.coffee} +381 -388
  156. data/spec_app/spec/javascripts/up/history_spec.js.coffee +21 -19
  157. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +4 -0
  158. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +27 -0
  159. data/spec_app/spec/javascripts/up/link_spec.js.coffee +163 -160
  160. data/spec_app/spec/javascripts/up/log_spec.js.coffee +85 -12
  161. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +141 -123
  162. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +117 -113
  163. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +60 -77
  164. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +1 -0
  165. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +85 -78
  166. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +29 -22
  167. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +14 -13
  168. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +9 -0
  169. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +96 -66
  170. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +37 -0
  171. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +31 -47
  172. data/spec_app/spec/javascripts/up/util_spec.js.coffee +725 -562
  173. data/spec_app/spec/javascripts/up/{layout_spec.js.coffee → viewport_spec.js.coffee} +175 -149
  174. metadata +57 -19
  175. data/lib/assets/javascripts/unpoly-bootstrap3/layout-ext.coffee +0 -5
  176. data/lib/assets/javascripts/unpoly/bus.coffee.erb +0 -518
  177. data/lib/assets/javascripts/unpoly/classes/extract_step.coffee +0 -4
  178. data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +0 -125
  179. data/lib/assets/javascripts/unpoly/params.coffee.erb +0 -522
  180. data/spec_app/spec/javascripts/helpers/append_fixture.js.coffee +0 -8
  181. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +0 -210
  182. data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +0 -9
  183. data/spec_app/spec/javascripts/up/params_spec.coffee +0 -768
  184. data/spec_app/vendor/asset-libs/jasmine-fixture-1.3.4/jasmine-fixture.js +0 -433
  185. data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/.bower.json +0 -26
  186. data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/jasmine-jquery.js +0 -838
@@ -8,9 +8,15 @@ class up.Record
8
8
  constructor: (options) ->
9
9
  u.assign(this, @attributes(options))
10
10
 
11
- attributes: (source = @) =>
11
+ attributes: (source = @) ->
12
12
  u.only(source, @fields()...)
13
13
 
14
- copy: (changes = {}) =>
14
+ "#{u.copy.key}": ->
15
+ @variant()
16
+
17
+ variant: (changes = {}) ->
15
18
  attributesWithChanges = u.merge(@attributes(), changes)
16
19
  new @constructor(attributesWithChanges)
20
+
21
+ "#{u.isEqual.key}": (other) ->
22
+ other && (@constructor == other.constructor) && u.isEqual(@attributes(), other.attributes())
@@ -0,0 +1,21 @@
1
+ (function() {
2
+ var u = up.util
3
+
4
+ up.Rect = function(props) {
5
+ u.assign(this, u.only(props, 'left', 'top', 'width', 'height'))
6
+ }
7
+
8
+ up.Rect.prototype = {
9
+ get bottom() {
10
+ return this.top + this.height
11
+ },
12
+ get right() {
13
+ return this.left + this.width
14
+ }
15
+ }
16
+
17
+ up.Rect.fromElement = function(element) {
18
+ return new up.Rect(element.getBoundingClientRect())
19
+ }
20
+
21
+ })()
@@ -1,6 +1,7 @@
1
1
  #= require ./record
2
2
 
3
3
  u = up.util
4
+ e = up.element
4
5
 
5
6
  ###**
6
7
  Instances of `up.Request` normalizes properties of an [`AJAX request`](/up.request)
@@ -27,10 +28,10 @@ class up.Request extends up.Record
27
28
  ###
28
29
 
29
30
  ###**
30
- [Parameters](/up.params) that should be sent as the request's payload.
31
+ [Parameters](/up.Params) that should be sent as the request's payload.
31
32
 
32
33
  @property up.Request#params
33
- @param {object|FormData|string|Array} params
34
+ @param {Object|FormData|string|Array} params
34
35
  @stable
35
36
  ###
36
37
 
@@ -54,7 +55,7 @@ class up.Request extends up.Record
54
55
  An object of additional HTTP headers.
55
56
 
56
57
  @property up.Request#headers
57
- @param {object} headers
58
+ @param {Object} headers
58
59
  @stable
59
60
  ###
60
61
 
@@ -65,7 +66,7 @@ class up.Request extends up.Record
65
66
  the timeout will not include the time spent waiting in the queue.
66
67
 
67
68
  @property up.Request#timeout
68
- @param {object|undefined} timeout
69
+ @param {Object|undefined} timeout
69
70
  @stable
70
71
  ###
71
72
  fields: ->
@@ -73,7 +74,6 @@ class up.Request extends up.Record
73
74
  'method',
74
75
  'url',
75
76
  'params',
76
- 'data', # deprecated. use #params.
77
77
  'target',
78
78
  'failTarget',
79
79
  'headers',
@@ -83,15 +83,27 @@ class up.Request extends up.Record
83
83
  ]
84
84
 
85
85
  ###**
86
+ Creates a new `up.Request` object.
87
+
88
+ This will not actually send the request over the network. For that use `up.request()`.
89
+
86
90
  @constructor up.Request
87
- @param {string} [attributes]
91
+ @param {string} attrs.url
92
+ @param {string} [attrs.method='get']
93
+ @param {up.Params|string|Object|Array} [attrs.params]
94
+ @param {string} [attrs.target]
95
+ @param {string} [attrs.failTarget]
96
+ @param {Object<string, string>} [attrs.headers]
97
+ @param {number} [attrs.timeout]
98
+ @internal
88
99
  ###
89
100
  constructor: (options) ->
101
+ up.legacy.fixKey(options, 'data', 'params')
90
102
  super(options)
91
103
  @normalize()
92
104
 
93
105
  normalize: =>
94
- u.deprecateRenamedKey(@, 'data', 'params')
106
+ @params = new up.Params(@params) # copies, which we want
95
107
  @method = u.normalizeMethod(@method)
96
108
  @headers ||= {}
97
109
  @extractHashFromUrl()
@@ -109,15 +121,16 @@ class up.Request extends up.Record
109
121
  @url = u.normalizeUrl(urlParts, hash: false)
110
122
 
111
123
  transferParamsToUrl: =>
112
- if @params && !u.isFormData(@params)
124
+ unless u.isBlank(@params)
113
125
  # GET methods are not allowed to have a payload, so we transfer { params } params to the URL.
114
- @url = up.params.buildURL(@url, @params)
126
+ @url = @params.toURL(@url)
115
127
  # Now that we have transfered the params into the URL, we delete them from the { params } option.
116
- @params = undefined
128
+ @params.clear()
117
129
 
118
130
  transferSearchToParams: =>
119
- if query = up.params.fromURL(@url)
120
- @params = up.params.merge(@params, query)
131
+ paramsFromQuery = up.Params.fromURL(@url)
132
+ unless u.isBlank(paramsFromQuery)
133
+ @params.addAll(paramsFromQuery)
121
134
  @url = u.normalizeUrl(@url, search: false)
122
135
 
123
136
  isSafe: =>
@@ -130,18 +143,14 @@ class up.Request extends up.Record
130
143
  xhr = new XMLHttpRequest()
131
144
 
132
145
  xhrHeaders = u.copy(@headers)
133
- xhrPayload = @params
134
- xhrMethod = @method
135
146
  xhrUrl = @url
147
+ xhrParams = u.copy(@params)
148
+ xhrMethod = up.proxy.wrapMethod(@method, xhrParams)
136
149
 
137
- [xhrMethod, xhrPayload] = up.proxy.wrapMethod(xhrMethod, xhrPayload)
138
-
139
- if xhrPayload
150
+ xhrPayload = null
151
+ unless u.isBlank(xhrParams)
140
152
  delete xhrHeaders['Content-Type'] # let the browser set the content type
141
- xhrPayload = up.params.toFormData(xhrPayload)
142
- else
143
- # XMLHttpRequest expects null for an empty body
144
- xhrPayload = null
153
+ xhrPayload = xhrParams.toFormData()
145
154
 
146
155
  pc = up.protocol.config
147
156
  xhrHeaders[pc.targetHeader] = @target if @target
@@ -176,9 +185,10 @@ class up.Request extends up.Record
176
185
  # The query section would be overridden by the serialized input values on submission.
177
186
  @transferSearchToParams()
178
187
 
179
- $form = $('<form class="up-page-loader"></form>')
188
+ form = e.affix(document.body, 'form.up-page-loader')
180
189
 
181
- addField = (field) -> $('<input type="hidden">').attr(field).appendTo($form)
190
+ addField = (attrs) ->
191
+ e.affix(form, 'input[type=hidden]', attrs)
182
192
 
183
193
  if @method == 'GET'
184
194
  formMethod = 'GET'
@@ -189,17 +199,18 @@ class up.Request extends up.Record
189
199
  addField(name: up.protocol.config.methodParam, value: @method)
190
200
  formMethod = 'POST'
191
201
 
192
- $form.attr(method: formMethod, action: @url)
202
+ e.setAttrs(form, method: formMethod, action: @url)
193
203
 
194
204
  if (csrfParam = up.protocol.csrfParam()) && (csrfToken = @csrfToken())
195
205
  addField(name: csrfParam, value: csrfToken)
196
206
 
197
207
  # @params will be undefined for GET requests, since we have already
198
208
  # transfered all params to the URL during normalize().
199
- u.each(up.params.toArray(@params), addField)
209
+ u.each(@params.toArray(), addField)
200
210
 
201
- $form.hide().appendTo('body')
202
- up.browser.submitForm($form)
211
+ e.hide(form)
212
+
213
+ up.browser.submitForm(form)
203
214
 
204
215
  # Returns a csrfToken if this request requires it
205
216
  csrfToken: =>
@@ -231,12 +242,7 @@ class up.Request extends up.Record
231
242
  @isSafe() && !u.isFormData(@params)
232
243
 
233
244
  cacheKey: =>
234
- query = up.params.toQuery(@params)
235
- [@url, @method, query, @target].join('|')
245
+ [@url, @method, @params.toQuery(), @target].join('|')
236
246
 
237
- @wrap: (object) ->
238
- if object instanceof @
239
- # This object has gone through instantiation and normalization before.
240
- object
241
- else
242
- new @(object)
247
+ @wrap: (value) ->
248
+ u.wrapValue(value, @)
@@ -8,9 +8,9 @@ Instances of `up.Response` describe the server response to an [`AJAX request`](/
8
8
  \#\#\# Example
9
9
 
10
10
  up.request('/foo').then(function(response) {
11
- console.log(response.status); // 200
12
- console.log(response.text); // "<html><body>..."
13
- });
11
+ console.log(response.status) // 200
12
+ console.log(response.text) // "<html><body>..."
13
+ })
14
14
 
15
15
  @class up.Response
16
16
  ###
@@ -97,6 +97,10 @@ class up.Response extends up.Record
97
97
  'title',
98
98
  ]
99
99
 
100
+ ###**
101
+ @constructor up.Response
102
+ @internal
103
+ ###
100
104
  constructor: (options) ->
101
105
  super(options)
102
106
 
@@ -0,0 +1,102 @@
1
+ e = up.element
2
+
3
+ class up.RevealMotion
4
+
5
+ constructor: (@element, options = {}) ->
6
+ layoutConfig = up.viewport.config
7
+ @viewport = options.viewport ? up.viewport.closest(@element)
8
+ up.legacy.fixKey(layoutConfig, 'snap', 'revealSnap')
9
+ snapDefault = layoutConfig.revealSnap
10
+ @snap = options.snap ? options.revealSnap ? snapDefault
11
+ if @snap == false
12
+ @snap = 0
13
+ else if @snap == true
14
+ @snap = snapDefault
15
+ @padding = options.padding ? options.revealPadding ? layoutConfig.revealPadding
16
+ @top = options.top
17
+ @fixedTop = options.fixedTop ? layoutConfig.fixedTop
18
+ @fixedBottom = options.fixedBottom ? layoutConfig.fixedBottom
19
+
20
+ # Options for up.ScrollMotion
21
+ @speed = options.speed ? options.scrollSpeed ? layoutConfig.scrollSpeed
22
+ @behavior = options.behavior ? options.scrollBehavior
23
+
24
+ start: ->
25
+ elementRect = up.Rect.fromElement(@element)
26
+ viewportRect = @getViewportRect(@viewport)
27
+
28
+ @addPadding(elementRect)
29
+ @substractObstructions(viewportRect)
30
+
31
+ if viewportRect.height <= 0
32
+ return Promise.reject(new Error('Viewport has no visible area'))
33
+
34
+ originalScrollTop = @viewport.scrollTop
35
+ newScrollTop = originalScrollTop
36
+
37
+ if @top || elementRect.height > viewportRect.height
38
+ # Element is either larger than the viewport,
39
+ # or the user has explicitely requested for the element to align at top
40
+ # => Scroll the viewport so the first element row is the first viewport row
41
+ diff = elementRect.top - viewportRect.top
42
+ newScrollTop += diff
43
+ else if elementRect.top < viewportRect.top
44
+ # Element fits within viewport, but sits too high
45
+ # => Scroll up (reduce scrollY), so the element comes down
46
+ newScrollTop -= (viewportRect.top - elementRect.top)
47
+ else if elementRect.bottom > viewportRect.bottom
48
+ # Element fits within viewport, but sits too low
49
+ # => Scroll down (increase scrollY), so the element comes up
50
+ newScrollTop += (elementRect.bottom - viewportRect.bottom)
51
+ else
52
+ # Element is fully visible within viewport
53
+ # => Do nothing
54
+
55
+ if newScrollTop < @snap && elementRect.top < (0.5 * viewportRect.height)
56
+ newScrollTop = 0
57
+
58
+ if newScrollTop != originalScrollTop
59
+ @scrollTo(newScrollTop)
60
+ else
61
+ Promise.resolve()
62
+
63
+ scrollTo: (newScrollTop) ->
64
+ scrollOptions =
65
+ speed: @speed
66
+ behavior: @behavior
67
+ @scrollMotion = new up.ScrollMotion(@viewport, newScrollTop, scrollOptions)
68
+ @scrollMotion.start()
69
+
70
+ getViewportRect: ->
71
+ if up.viewport.isRoot(@viewport)
72
+ # Other than an element with overflow-y, the document viewport
73
+ # stretches to the full height of its contents. So we create a viewport
74
+ # sized to the usuable screen area.
75
+ new up.Rect
76
+ left: 0
77
+ top: 0
78
+ width: up.viewport.rootWidth()
79
+ height: up.viewport.rootHeight()
80
+ else
81
+ up.Rect.fromElement(@viewport)
82
+
83
+ addPadding: (elementRect) ->
84
+ elementRect.top -= @padding
85
+ elementRect.height += 2 * @padding
86
+
87
+ substractObstructions: (viewportRect) ->
88
+ for obstruction in e.list(@fixedTop...)
89
+ obstructionRect = up.Rect.fromElement(obstruction)
90
+ diff = obstructionRect.bottom - viewportRect.top
91
+ if diff > 0
92
+ viewportRect.top += diff
93
+ viewportRect.height -= diff
94
+
95
+ for obstruction in e.list(@fixedBottom...)
96
+ obstructionRect = up.Rect.fromElement(obstruction)
97
+ diff = viewportRect.bottom - obstructionRect.top
98
+ if diff > 0
99
+ viewportRect.height -= diff
100
+
101
+ finish: ->
102
+ @scrollMotion?.finish()
@@ -0,0 +1,67 @@
1
+ u = up.util
2
+
3
+ class up.ScrollMotion
4
+
5
+ # We want to make the default speed mimic Chrome's smooth scrolling behavior.
6
+ # We also want to keep the default valuein up.viewport.config.scrollSpeed to be 1.
7
+ # For our calculation in #animationFrame() we need to multiply it with this factor.
8
+ SPEED_CALIBRATION = 0.065
9
+
10
+ constructor: (@scrollable, @targetTop, options = {}) ->
11
+ # The option for up.scroll() is { behavior }, but coming
12
+ # from up.replace() it's { scrollBehavior }.
13
+ @behavior = options.behavior ? options.scrollBehavior ? 'instant'
14
+
15
+ # The option for up.scroll() is { behavior }, but coming
16
+ # from up.replace() it's { scrollSpeed }.
17
+ @speed = (options.speed ? options.scrollSpeed ? up.viewport.config.scrollSpeed) * SPEED_CALIBRATION
18
+
19
+ start: =>
20
+ return new Promise (@resolve, @reject) =>
21
+ if @behavior == 'smooth' && up.motion.isEnabled()
22
+ @startAnimation()
23
+ else
24
+ @finish()
25
+
26
+ startAnimation: ->
27
+ @startTime = Date.now()
28
+ @startTop = @scrollable.scrollTop
29
+ @topDiff = @targetTop - @startTop
30
+ # We're applying a square root to become slower for small distances
31
+ # and faster for large distances.
32
+ @duration = Math.sqrt(Math.abs(@topDiff)) / @speed
33
+ requestAnimationFrame(@animationFrame)
34
+
35
+ animationFrame: =>
36
+ return if @settled
37
+
38
+ # When the scroll position is not the one we previously set, we assume
39
+ # that the user has tried scrolling on her own. We then cancel the scrolling animation.
40
+ if @frameTop && Math.abs(@frameTop - @scrollable.scrollTop) > 1.5
41
+ @cancel('Animation aborted due to user intervention')
42
+
43
+ currentTime = Date.now()
44
+ timeElapsed = currentTime - @startTime
45
+ timeFraction = Math.min(timeElapsed / @duration, 1)
46
+
47
+ @frameTop = @startTop + (u.simpleEase(timeFraction) * @topDiff)
48
+
49
+ # When we're very close to the target top, finish the animation
50
+ # directly to deal with rounding errors.
51
+ if Math.abs(@targetTop - @frameTop) < 0.3
52
+ @finish()
53
+ else
54
+ @scrollable.scrollTop = @frameTop
55
+ requestAnimationFrame(@animationFrame)
56
+
57
+ cancel: (reason) =>
58
+ @settled = true
59
+ @reject(new Error(reason))
60
+
61
+ finish: =>
62
+ # In case we're animating with emulation, cancel the next scheduled frame
63
+ @settled = true
64
+ # Setting the { scrollTop } prop will also finish a native scrolling
65
+ # animation in Firefox and Chrome.
66
+ @scrollable.scrollTop = @targetTop
67
+ @resolve()
@@ -0,0 +1,60 @@
1
+ u = up.util
2
+
3
+ class up.Selector
4
+
5
+ CSS_HAS_SUFFIX_PATTERN = new RegExp("\\:has\\(([^\\)]+)\\)$")
6
+ MATCH_FN_NAME = if up.browser.isIE11() then 'msMatchesSelector' else 'matches'
7
+
8
+ constructor: (@selector, @filterFn) ->
9
+
10
+ matches: (element) ->
11
+ doesMatch = element[MATCH_FN_NAME](@selector)
12
+ doesMatch &&= @filterFn(element) if @filterFn
13
+ doesMatch
14
+
15
+ descendants: (root) ->
16
+ matches = root.querySelectorAll(@selector)
17
+ if @filterFn
18
+ matches = u.filter(matches, @filterFn)
19
+ matches
20
+
21
+ descendant: (root) ->
22
+ if !@filterFn
23
+ root.querySelector(@selector)
24
+ else
25
+ candidates = root.querySelectorAll(@selector)
26
+ u.find(candidates, @filterFn)
27
+
28
+ subtree: (root) ->
29
+ matches = []
30
+ if @matches(root)
31
+ matches.push(root)
32
+ matches.push(@descendants(root)...)
33
+ matches
34
+
35
+ closest: (root) ->
36
+ if root.closest && !@filterFn
37
+ return root.closest(@selector)
38
+ else
39
+ return @closestPolyfill(root)
40
+
41
+ closestPolyfill: (root) ->
42
+ if @matches(root, @selector)
43
+ root
44
+ else
45
+ @ancestor(root)
46
+
47
+ ancestor: (element) ->
48
+ if parentElement = element.parentElement
49
+ if @matches(parentElement)
50
+ parentElement
51
+ else
52
+ @ancestor(parentElement)
53
+
54
+ @parse: (selector) ->
55
+ filter = null
56
+ selector = selector.replace CSS_HAS_SUFFIX_PATTERN, (match, descendantSelector) ->
57
+ filter = (element) ->
58
+ element.querySelector(descendantSelector)
59
+ return ''
60
+ new @(selector, filter)