unpoly-rails 0.57.0 → 0.60.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.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +393 -1
- data/Gemfile.lock +5 -2
- data/README.md +1 -1
- data/README_RAILS.md +1 -1
- data/Rakefile +10 -1
- data/design/es6.js +32 -0
- data/design/ie11.txt +9 -0
- data/design/measure_jquery/element_list.js +41 -0
- data/design/measure_jquery/up.on_vs_addEventListener.js +56 -0
- data/design/todo_jquery.txt +13 -0
- data/dist/unpoly-bootstrap3.js +8 -8
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.css +22 -20
- data/dist/unpoly.js +6990 -5336
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +4 -4
- data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +5 -0
- data/lib/assets/javascripts/unpoly.coffee +8 -6
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +23 -118
- data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +36 -0
- data/lib/assets/javascripts/unpoly/classes/cache.coffee +4 -4
- data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +45 -39
- data/lib/assets/javascripts/unpoly/classes/config.coffee +9 -0
- data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +18 -27
- data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +39 -0
- data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +116 -0
- data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +8 -8
- data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +19 -19
- data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +54 -31
- data/lib/assets/javascripts/unpoly/classes/{focus_tracker.coffee → focus_follower.coffee} +2 -2
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +25 -25
- data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +4 -11
- data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +157 -0
- data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +525 -0
- data/lib/assets/javascripts/unpoly/classes/record.coffee +8 -2
- data/lib/assets/javascripts/unpoly/classes/rect.js +21 -0
- data/lib/assets/javascripts/unpoly/classes/request.coffee +41 -35
- data/lib/assets/javascripts/unpoly/classes/response.coffee +7 -3
- data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +102 -0
- data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +67 -0
- data/lib/assets/javascripts/unpoly/classes/selector.coffee +60 -0
- data/lib/assets/javascripts/unpoly/classes/tether.coffee +105 -0
- data/lib/assets/javascripts/unpoly/classes/url_set.coffee +12 -7
- data/lib/assets/javascripts/unpoly/element.coffee.erb +1126 -0
- data/lib/assets/javascripts/unpoly/event.coffee.erb +437 -0
- data/lib/assets/javascripts/unpoly/feedback.coffee +73 -94
- data/lib/assets/javascripts/unpoly/form.coffee.erb +188 -181
- data/lib/assets/javascripts/unpoly/{dom.coffee.erb → fragment.coffee.erb} +250 -283
- data/lib/assets/javascripts/unpoly/framework.coffee +67 -0
- data/lib/assets/javascripts/unpoly/history.coffee +29 -28
- data/lib/assets/javascripts/unpoly/legacy.coffee +60 -0
- data/lib/assets/javascripts/unpoly/link.coffee.erb +127 -119
- data/lib/assets/javascripts/unpoly/log.coffee +99 -19
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +95 -118
- data/lib/assets/javascripts/unpoly/motion.coffee.erb +158 -138
- data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
- data/lib/assets/javascripts/unpoly/popup.coffee.erb +119 -102
- data/lib/assets/javascripts/unpoly/protocol.coffee +11 -15
- data/lib/assets/javascripts/unpoly/proxy.coffee +62 -65
- data/lib/assets/javascripts/unpoly/radio.coffee +3 -5
- data/lib/assets/javascripts/unpoly/rails.coffee +8 -9
- data/lib/assets/javascripts/unpoly/syntax.coffee.erb +173 -125
- data/lib/assets/javascripts/unpoly/toast.coffee +25 -24
- data/lib/assets/javascripts/unpoly/tooltip.coffee +89 -79
- data/lib/assets/javascripts/unpoly/util.coffee.erb +579 -1074
- data/lib/assets/javascripts/unpoly/{layout.coffee.erb → viewport.coffee.erb} +334 -264
- data/lib/assets/stylesheets/unpoly/dom.sass +1 -1
- data/lib/assets/stylesheets/unpoly/layout.sass +2 -0
- data/lib/assets/stylesheets/unpoly/popup.sass +0 -1
- data/lib/assets/stylesheets/unpoly/tooltip.sass +17 -12
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -2
- data/spec_app/Gemfile +2 -1
- data/spec_app/Gemfile.lock +38 -27
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -2
- data/spec_app/app/assets/stylesheets/integration_test.sass +14 -1
- data/spec_app/app/controllers/scroll_test_controller.rb +5 -0
- data/spec_app/app/views/css_test/modal.erb +6 -6
- data/spec_app/app/views/css_test/popup.erb +44 -18
- data/spec_app/app/views/css_test/tooltip.erb +23 -4
- data/spec_app/app/views/error_test/trigger.erb +1 -1
- data/spec_app/app/views/form_test/basics/new.erb +1 -3
- data/spec_app/app/views/pages/start.erb +9 -2
- data/spec_app/app/views/reveal_test/long1.erb +1 -1
- data/spec_app/app/views/reveal_test/long2.erb +1 -1
- data/spec_app/app/views/reveal_test/within_document_viewport.erb +24 -0
- data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +28 -0
- data/spec_app/app/views/scroll_test/long1.erb +30 -0
- data/spec_app/config/routes.rb +1 -0
- data/spec_app/spec/javascripts/helpers/agent_detector.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +17 -5
- data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/fixture.js.coffee +25 -0
- data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +1 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +2 -2
- data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +4 -1
- data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +2 -1
- data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +2 -2
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +18 -11
- data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/spec_util.coffee +47 -0
- data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_array.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +6 -2
- data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +6 -2
- data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +8 -0
- data/spec_app/spec/javascripts/helpers/to_be_error.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +8 -0
- data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +1 -2
- data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +7 -0
- data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +7 -0
- data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +8 -0
- data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +7 -3
- data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -21
- data/spec_app/spec/javascripts/helpers/to_match_list.coffee +14 -0
- data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +4 -1
- data/spec_app/spec/javascripts/helpers/to_match_url.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/trigger.js.coffee +91 -7
- data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +3 -0
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +23 -90
- data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +3 -0
- data/spec_app/spec/javascripts/up/classes/config_spec.coffee +24 -0
- data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +45 -0
- data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +5 -2
- data/spec_app/spec/javascripts/up/classes/params_spec.coffee +557 -0
- data/spec_app/spec/javascripts/up/classes/request_spec.coffee +7 -4
- data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +51 -0
- data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +3 -0
- data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +3 -2
- data/spec_app/spec/javascripts/up/element_spec.coffee +897 -0
- data/spec_app/spec/javascripts/up/event_spec.js.coffee +496 -0
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +69 -48
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +252 -194
- data/spec_app/spec/javascripts/up/{dom_spec.js.coffee → fragment_spec.js.coffee} +381 -388
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +21 -19
- data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +4 -0
- data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +27 -0
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +163 -160
- data/spec_app/spec/javascripts/up/log_spec.js.coffee +85 -12
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +141 -123
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +117 -113
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +60 -77
- data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +1 -0
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +85 -78
- data/spec_app/spec/javascripts/up/radio_spec.js.coffee +29 -22
- data/spec_app/spec/javascripts/up/rails_spec.js.coffee +14 -13
- data/spec_app/spec/javascripts/up/spec_spec.js.coffee +9 -0
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +96 -66
- data/spec_app/spec/javascripts/up/toast_spec.js.coffee +37 -0
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +31 -47
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +725 -562
- data/spec_app/spec/javascripts/up/{layout_spec.js.coffee → viewport_spec.js.coffee} +175 -149
- metadata +57 -19
- data/lib/assets/javascripts/unpoly-bootstrap3/layout-ext.coffee +0 -5
- data/lib/assets/javascripts/unpoly/bus.coffee.erb +0 -518
- data/lib/assets/javascripts/unpoly/classes/extract_step.coffee +0 -4
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +0 -125
- data/lib/assets/javascripts/unpoly/params.coffee.erb +0 -522
- data/spec_app/spec/javascripts/helpers/append_fixture.js.coffee +0 -8
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +0 -210
- data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +0 -9
- data/spec_app/spec/javascripts/up/params_spec.coffee +0 -768
- data/spec_app/vendor/asset-libs/jasmine-fixture-1.3.4/jasmine-fixture.js +0 -433
- data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/.bower.json +0 -26
- data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/jasmine-jquery.js +0 -838
@@ -1,125 +0,0 @@
|
|
1
|
-
u = up.util
|
2
|
-
|
3
|
-
class up.MotionTracker
|
4
|
-
|
5
|
-
constructor: (name) ->
|
6
|
-
@activeClass = "up-#{name}"
|
7
|
-
@dataKey = "up-#{name}-finished"
|
8
|
-
@selector = ".#{@activeClass}"
|
9
|
-
@finishEvent = "up:#{name}:finish"
|
10
|
-
@finishCount = 0
|
11
|
-
@clusterCount = 0
|
12
|
-
|
13
|
-
###**
|
14
|
-
Finishes all animations in the given element cluster's ancestors and descendants,
|
15
|
-
then calls the animator.
|
16
|
-
|
17
|
-
The animation returned by the animator is tracked so it can be
|
18
|
-
[`finished`](/up.MotionTracker.finish) later.
|
19
|
-
|
20
|
-
@method claim
|
21
|
-
@param {jQuery} $cluster
|
22
|
-
@param {Function(jQuery): Promise} animator
|
23
|
-
@param {Object} memory.trackMotion = true
|
24
|
-
Whether
|
25
|
-
@return {Promise} A promise that is fulfilled when the new animation ends.
|
26
|
-
###
|
27
|
-
claim: (cluster, animator, memory = {}) =>
|
28
|
-
$cluster = $(cluster)
|
29
|
-
memory.trackMotion = u.option(memory.trackMotion, up.motion.isEnabled())
|
30
|
-
if memory.trackMotion is false
|
31
|
-
# Since we don't want recursive tracking or finishing, we could run
|
32
|
-
# the animator() now. However, since the else branch is async, we push
|
33
|
-
# the animator into the microtask queue to be async as well.
|
34
|
-
u.microtask(animator)
|
35
|
-
else
|
36
|
-
memory.trackMotion = false
|
37
|
-
@finish($cluster).then =>
|
38
|
-
promise = @whileForwardingFinishEvent($cluster, animator)
|
39
|
-
promise = promise.then => @unmarkCluster($cluster)
|
40
|
-
# Attach the modified promise to the cluster's elements
|
41
|
-
@markCluster($cluster, promise)
|
42
|
-
promise
|
43
|
-
|
44
|
-
###**
|
45
|
-
@method finish
|
46
|
-
@param {jQuery} [elements]
|
47
|
-
If no element is given, finishes all animations in the documnet.
|
48
|
-
If an element is given, only finishes animations in its subtree and ancestors.
|
49
|
-
@return {Promise} A promise that is fulfilled when animations have finished.
|
50
|
-
###
|
51
|
-
finish: (elements) =>
|
52
|
-
@finishCount++
|
53
|
-
return Promise.resolve() if @clusterCount == 0 || !up.motion.isEnabled()
|
54
|
-
$elements = @expandFinishRequest(elements)
|
55
|
-
allFinished = u.map($elements, @finishOneElement)
|
56
|
-
Promise.all(allFinished)
|
57
|
-
|
58
|
-
expandFinishRequest: (elements) =>
|
59
|
-
if elements
|
60
|
-
u.selectInDynasty($(elements), @selector)
|
61
|
-
else
|
62
|
-
$(@selector)
|
63
|
-
|
64
|
-
isActive: (element) =>
|
65
|
-
u.hasClass(element, @activeClass)
|
66
|
-
|
67
|
-
finishOneElement: (element) =>
|
68
|
-
$element = $(element)
|
69
|
-
|
70
|
-
# Animating code is expected to listen to this event, fast-forward
|
71
|
-
# the animation and resolve their promise. All built-ins like
|
72
|
-
# `up.animate`, `up.morph`, or `up.scroll` behave that way.
|
73
|
-
@emitFinishEvent($element)
|
74
|
-
|
75
|
-
# If animating code ignores the event, we cannot force the animation to
|
76
|
-
# finish from here. We will wait for the animation to end naturally before
|
77
|
-
# starting the next animation.
|
78
|
-
@whenElementFinished($element)
|
79
|
-
|
80
|
-
emitFinishEvent: ($element, eventAttrs = {}) =>
|
81
|
-
eventAttrs = u.merge({ $element: $element, message: false }, eventAttrs)
|
82
|
-
up.emit(@finishEvent, eventAttrs)
|
83
|
-
|
84
|
-
whenElementFinished: ($element) =>
|
85
|
-
# There are some cases related to element ghosting where an element
|
86
|
-
# has the class, but not the data value. In that case simply return
|
87
|
-
# a resolved promise.
|
88
|
-
$element.data(@dataKey) || Promise.resolve()
|
89
|
-
|
90
|
-
markCluster: ($cluster, promise) =>
|
91
|
-
@clusterCount++
|
92
|
-
$cluster.addClass(@activeClass)
|
93
|
-
$cluster.data(@dataKey, promise)
|
94
|
-
|
95
|
-
unmarkCluster: ($cluster) =>
|
96
|
-
@clusterCount--
|
97
|
-
$cluster.removeClass(@activeClass)
|
98
|
-
$cluster.removeData(@dataKey)
|
99
|
-
|
100
|
-
forwardFinishEvent: ($original, $ghost, duration) =>
|
101
|
-
@start $original, =>
|
102
|
-
doForward = => $ghost.trigger(@finishEvent)
|
103
|
-
# Forward the finish event to the $ghost that is actually animating
|
104
|
-
$original.on @finishEvent, doForward
|
105
|
-
# Our own pseudo-animation finishes when the actual animation on $ghost finishes
|
106
|
-
duration.then => $original.off @finishEvent, doForward
|
107
|
-
|
108
|
-
whileForwardingFinishEvent: ($elements, fn) =>
|
109
|
-
return fn() if $elements.length < 2
|
110
|
-
doForward = (event) =>
|
111
|
-
unless event.forwarded
|
112
|
-
u.each $elements, (element) =>
|
113
|
-
$element = $(element)
|
114
|
-
if element != event.target && @isActive($element)
|
115
|
-
@emitFinishEvent($element, forwarded: true)
|
116
|
-
|
117
|
-
# Forward the finish event to the $ghost that is actually animating
|
118
|
-
$elements.on @finishEvent, doForward
|
119
|
-
# Our own pseudo-animation finishes when the actual animation on $ghost finishes
|
120
|
-
fn().then => $elements.off @finishEvent, doForward
|
121
|
-
|
122
|
-
reset: =>
|
123
|
-
@finish().then =>
|
124
|
-
@finishCount = 0
|
125
|
-
@clusterCount = 0
|
@@ -1,522 +0,0 @@
|
|
1
|
-
###**
|
2
|
-
Request parameters
|
3
|
-
==================
|
4
|
-
|
5
|
-
Methods like [`up.replace()`](/up.replace) accept request parameters (or form data values) as a `{ params }` option.
|
6
|
-
|
7
|
-
This module offers a consistent API to read and manipulate request parameters independent of their type.
|
8
|
-
|
9
|
-
|
10
|
-
\#\#\# Supported parameter types
|
11
|
-
|
12
|
-
The following types of parameters are supported:
|
13
|
-
|
14
|
-
1. an object like `{ email: 'foo@bar.com' }`
|
15
|
-
2. a [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object
|
16
|
-
3. a query string like `email=foo%40bar.com`
|
17
|
-
4. an array of `{ name, value }` objects like `[{ name: 'email', value: 'foo@bar.com' }]`
|
18
|
-
|
19
|
-
@class up.params
|
20
|
-
###
|
21
|
-
up.params = (($) ->
|
22
|
-
u = up.util
|
23
|
-
|
24
|
-
NATURE_MISSING = 0
|
25
|
-
NATURE_ARRAY = 1
|
26
|
-
NATURE_QUERY = 2
|
27
|
-
NATURE_FORM_DATA = 3
|
28
|
-
NATURE_OBJECT = 4
|
29
|
-
|
30
|
-
natureOf = (params) ->
|
31
|
-
if u.isMissing(params)
|
32
|
-
NATURE_MISSING
|
33
|
-
else if u.isArray(params)
|
34
|
-
NATURE_ARRAY
|
35
|
-
else if u.isString(params)
|
36
|
-
NATURE_QUERY
|
37
|
-
else if u.isFormData(params)
|
38
|
-
NATURE_FORM_DATA
|
39
|
-
else if u.isObject(params)
|
40
|
-
NATURE_OBJECT
|
41
|
-
else
|
42
|
-
up.fail("Unsupport params type: %o", params)
|
43
|
-
|
44
|
-
###**
|
45
|
-
Returns an array representation of the given `params`.
|
46
|
-
|
47
|
-
The given params value may be of any [supported type](/up.params).
|
48
|
-
|
49
|
-
Each element in the returned array is an object with `{ name }` and `{ value }` properties.
|
50
|
-
|
51
|
-
\#\#\# Example
|
52
|
-
|
53
|
-
var array = up.params.toArray('foo=bar&baz=bam')
|
54
|
-
|
55
|
-
// array is now: [
|
56
|
-
// { name: 'foo', value: 'bar' },
|
57
|
-
// { name: 'baz', value: 'bam' },
|
58
|
-
// ]
|
59
|
-
|
60
|
-
@function up.params.toArray
|
61
|
-
@param {Object|FormData|string|Array|undefined} params
|
62
|
-
the params to convert
|
63
|
-
@return {Array}
|
64
|
-
an array representation of the given params
|
65
|
-
@experimental
|
66
|
-
###
|
67
|
-
toArray = (params) ->
|
68
|
-
switch natureOf(params)
|
69
|
-
when NATURE_MISSING
|
70
|
-
[]
|
71
|
-
when NATURE_ARRAY
|
72
|
-
params
|
73
|
-
when NATURE_QUERY
|
74
|
-
buildArrayFromQuery(params)
|
75
|
-
when NATURE_FORM_DATA
|
76
|
-
buildArrayFromFormData(params)
|
77
|
-
when NATURE_OBJECT
|
78
|
-
buildArrayFromObject(params)
|
79
|
-
|
80
|
-
###**
|
81
|
-
Returns an object representation of the given `params`.
|
82
|
-
|
83
|
-
The given params value may be of any [supported type](/up.params).
|
84
|
-
|
85
|
-
The returned value is a simple JavaScript object whose properties correspond
|
86
|
-
to the key/values in the given `params`.
|
87
|
-
|
88
|
-
\#\#\# Example
|
89
|
-
|
90
|
-
var object = up.params.toObject('foo=bar&baz=bam')
|
91
|
-
|
92
|
-
// object is now: {
|
93
|
-
// foo: 'bar',
|
94
|
-
// baz: 'bam'
|
95
|
-
// ]
|
96
|
-
|
97
|
-
@function up.params.toObject
|
98
|
-
@param {Object|FormData|string|Array|undefined} params
|
99
|
-
the params to convert
|
100
|
-
@return {Array}
|
101
|
-
an object representation of the given params
|
102
|
-
@experimental
|
103
|
-
###
|
104
|
-
toObject = (params) ->
|
105
|
-
switch natureOf(params)
|
106
|
-
when NATURE_MISSING
|
107
|
-
{}
|
108
|
-
when NATURE_ARRAY, NATURE_QUERY, NATURE_FORM_DATA
|
109
|
-
buildObjectFromArray(toArray(params))
|
110
|
-
when NATURE_OBJECT
|
111
|
-
params
|
112
|
-
|
113
|
-
###**
|
114
|
-
Returns [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) representation of the given `params`.
|
115
|
-
|
116
|
-
The given params value may be of any [supported type](/up.params).
|
117
|
-
|
118
|
-
\#\#\# Example
|
119
|
-
|
120
|
-
var formData = up.params.toFormData('foo=bar&baz=bam')
|
121
|
-
|
122
|
-
formData.get('foo') // 'bar'
|
123
|
-
formData.get('baz') // 'bam'
|
124
|
-
|
125
|
-
@function up.params.toFormData
|
126
|
-
@param {Object|FormData|string|Array|undefined} params
|
127
|
-
the params to convert
|
128
|
-
@return {FormData}
|
129
|
-
a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) representation of the given params
|
130
|
-
@experimental
|
131
|
-
###
|
132
|
-
toFormData = (params) ->
|
133
|
-
switch natureOf(params)
|
134
|
-
when NATURE_MISSING
|
135
|
-
# Return an empty FormData object
|
136
|
-
new FormData()
|
137
|
-
when NATURE_ARRAY, NATURE_QUERY, NATURE_OBJECT
|
138
|
-
buildFormDataFromArray(toArray(params))
|
139
|
-
when NATURE_FORM_DATA
|
140
|
-
params
|
141
|
-
|
142
|
-
###**
|
143
|
-
Returns an query string for the given `params`.
|
144
|
-
|
145
|
-
The given params value may be of any [supported type](/up.params).
|
146
|
-
|
147
|
-
The keys and values in the returned query string will be [percent-encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding).
|
148
|
-
Non-primitive values (like [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) will be omitted from
|
149
|
-
the retuned query string.
|
150
|
-
|
151
|
-
\#\#\# Example
|
152
|
-
|
153
|
-
var query = up.params.toQuery({ foo: 'bar', baz: 'bam' })
|
154
|
-
|
155
|
-
// query is now: 'foo=bar&baz=bam'
|
156
|
-
|
157
|
-
@function up.params.toQuery
|
158
|
-
@param {Object|FormData|string|Array|undefined} params
|
159
|
-
the params to convert
|
160
|
-
@return {string}
|
161
|
-
a query string built from the given params
|
162
|
-
@experimental
|
163
|
-
###
|
164
|
-
toQuery = (params) ->
|
165
|
-
switch natureOf(params)
|
166
|
-
when NATURE_MISSING
|
167
|
-
''
|
168
|
-
when NATURE_QUERY
|
169
|
-
params
|
170
|
-
when NATURE_ARRAY, NATURE_FORM_DATA, NATURE_OBJECT
|
171
|
-
buildQueryFromArray(toArray(params))
|
172
|
-
|
173
|
-
arrayEntryToQuery = (entry) ->
|
174
|
-
value = entry.value
|
175
|
-
return undefined unless isPrimitiveValue(value)
|
176
|
-
query = encodeURIComponent(entry.name)
|
177
|
-
# There is a subtle difference when encoding blank values:
|
178
|
-
# 1. An undefined or null value is encoded to `key` with no equals sign
|
179
|
-
# 2. An empty string value is encoded to `key=` with an equals sign but no value
|
180
|
-
if u.isGiven(value)
|
181
|
-
query += "="
|
182
|
-
query += encodeURIComponent(value)
|
183
|
-
query
|
184
|
-
|
185
|
-
###**
|
186
|
-
Returns whether the given value can be encoded into a query string.
|
187
|
-
|
188
|
-
We will have `File` values in our params when we serialize a form with a file input.
|
189
|
-
These entries will be filtered out when converting to a query string.
|
190
|
-
###
|
191
|
-
isPrimitiveValue = (value) ->
|
192
|
-
u.isMissing(value) || u.isString(value) || u.isNumber(value) || u.isBoolean(value)
|
193
|
-
|
194
|
-
safeSet = (obj, k, value) ->
|
195
|
-
obj[k] = value unless u.isBasicObjectProperty(k)
|
196
|
-
|
197
|
-
safeGet = (obj, k) ->
|
198
|
-
obj[k] unless u.isBasicObjectProperty(k)
|
199
|
-
|
200
|
-
buildQueryFromArray = (array) ->
|
201
|
-
parts = u.map(array, arrayEntryToQuery)
|
202
|
-
parts = u.compact(parts)
|
203
|
-
parts.join('&')
|
204
|
-
|
205
|
-
buildArrayFromQuery = (query) ->
|
206
|
-
array = []
|
207
|
-
for part in query.split('&')
|
208
|
-
if part
|
209
|
-
[name, value] = part.split('=')
|
210
|
-
name = decodeURIComponent(name)
|
211
|
-
# There are three forms we need to handle:
|
212
|
-
# (1) foo=bar should become { name: 'foo', bar: 'bar' }
|
213
|
-
# (2) foo= should become { name: 'foo', bar: '' }
|
214
|
-
# (3) foo should become { name: 'foo', bar: null }
|
215
|
-
if u.isGiven(value)
|
216
|
-
value = decodeURIComponent(value)
|
217
|
-
else
|
218
|
-
value = null
|
219
|
-
array.push({ name, value })
|
220
|
-
array
|
221
|
-
|
222
|
-
buildArrayFromObject = (object) ->
|
223
|
-
array = []
|
224
|
-
for k, v of object
|
225
|
-
array.push(name: k, value: v)
|
226
|
-
array
|
227
|
-
|
228
|
-
buildObjectFromArray = (array) ->
|
229
|
-
obj = {}
|
230
|
-
for entry in array
|
231
|
-
safeSet(obj, entry.name, entry.value)
|
232
|
-
obj
|
233
|
-
|
234
|
-
buildArrayFromFormData = (formData) ->
|
235
|
-
array = []
|
236
|
-
u.eachIterator formData.entries(), (value) ->
|
237
|
-
[name, value] = value
|
238
|
-
array.push({ name, value })
|
239
|
-
array
|
240
|
-
|
241
|
-
buildFormDataFromArray = (array) ->
|
242
|
-
formData = new FormData()
|
243
|
-
for entry in array
|
244
|
-
formData.append(entry.name, entry.value)
|
245
|
-
<% if ENV['JS_KNIFE'] %>formData.originalArray = array<% end %>
|
246
|
-
formData
|
247
|
-
|
248
|
-
buildURL = (base, params) ->
|
249
|
-
parts = [base, toQuery(params)]
|
250
|
-
parts = u.select(parts, u.isPresent)
|
251
|
-
separator = if u.contains(base, '?') then '&' else '?'
|
252
|
-
parts.join(separator)
|
253
|
-
|
254
|
-
###**
|
255
|
-
Adds to the given `params` a new entry with the given `name` and `value`.
|
256
|
-
|
257
|
-
The given params value may be of any [supported type](/up.params).
|
258
|
-
|
259
|
-
The given `params` value is changed in-place, if possible. Some types, such as query strings,
|
260
|
-
cannot be changed in-place. The return value is always a params value that includes the new entry.
|
261
|
-
|
262
|
-
\#\#\# Example
|
263
|
-
|
264
|
-
var obj = { foo: 'bar' }
|
265
|
-
up.params.add(obj, 'baz', 'bam')
|
266
|
-
// obj is now: { foo: 'bar', baz: 'bam' }
|
267
|
-
|
268
|
-
@function up.params.add
|
269
|
-
@param {string|object|FormData|Array|undefined} params
|
270
|
-
@param {string} name
|
271
|
-
@param {any} value
|
272
|
-
@return {string|object|FormData|Array}
|
273
|
-
@experimental
|
274
|
-
###
|
275
|
-
add = (params, name, value) ->
|
276
|
-
newEntry = [{ name, value }]
|
277
|
-
assign(params, newEntry)
|
278
|
-
|
279
|
-
###**
|
280
|
-
Returns a new params value that contains entries from both `params` and `otherParams`.
|
281
|
-
|
282
|
-
The given params value may be of any [supported type](/up.params).
|
283
|
-
|
284
|
-
This function creates a new params value. The given `params` argument is not changed.
|
285
|
-
|
286
|
-
@function up.params.merge
|
287
|
-
@param {string|object|FormData|Array|undefined} params
|
288
|
-
@param {string|object|FormData|Array|undefined} otherParams
|
289
|
-
@return {string|object|FormData|Array}
|
290
|
-
@experimental
|
291
|
-
###
|
292
|
-
merge = (params, otherParams) ->
|
293
|
-
switch natureOf(params)
|
294
|
-
when NATURE_MISSING
|
295
|
-
merge({}, otherParams)
|
296
|
-
when NATURE_ARRAY
|
297
|
-
otherArray = toArray(otherParams)
|
298
|
-
params.concat(otherArray)
|
299
|
-
when NATURE_FORM_DATA
|
300
|
-
formData = new FormData()
|
301
|
-
assign(formData, params)
|
302
|
-
assign(formData, otherParams)
|
303
|
-
formData
|
304
|
-
when NATURE_QUERY
|
305
|
-
otherQuery = toQuery(otherParams)
|
306
|
-
parts = u.select([params, otherQuery], u.isPresent)
|
307
|
-
parts.join('&')
|
308
|
-
when NATURE_OBJECT
|
309
|
-
u.merge(params, toObject(otherParams))
|
310
|
-
|
311
|
-
###**
|
312
|
-
Returns the first param value with the given `name` from the given `params`.
|
313
|
-
|
314
|
-
The given params value may be of any [supported type](/up.params).
|
315
|
-
|
316
|
-
\#\#\# Example
|
317
|
-
|
318
|
-
var array = [
|
319
|
-
{ name: 'foo', value: 'bar' },
|
320
|
-
{ name: 'baz', value: 'bam' }
|
321
|
-
}
|
322
|
-
|
323
|
-
value = up.params.get(array, 'baz')
|
324
|
-
// value is now: 'bam'
|
325
|
-
|
326
|
-
@function up.params.get
|
327
|
-
@experimental
|
328
|
-
###
|
329
|
-
get = (params, name) ->
|
330
|
-
switch natureOf(params)
|
331
|
-
when NATURE_MISSING
|
332
|
-
undefined
|
333
|
-
when NATURE_ARRAY
|
334
|
-
entry = u.detect(params, (entry) -> entry.name == name)
|
335
|
-
entry?.value
|
336
|
-
when NATURE_FORM_DATA
|
337
|
-
value = params.get(name)
|
338
|
-
value = undefined if u.isNull(value)
|
339
|
-
value
|
340
|
-
when NATURE_QUERY
|
341
|
-
safeGet(toObject(params), name)
|
342
|
-
when NATURE_OBJECT
|
343
|
-
safeGet(params, name)
|
344
|
-
|
345
|
-
###**
|
346
|
-
Extends the given `params` with entries from the given `otherParams`.
|
347
|
-
|
348
|
-
The given params value may be of any [supported type](/up.params).
|
349
|
-
|
350
|
-
The given `params` is changed in-place, if possible. Some types, such as query strings,
|
351
|
-
cannot be changed in-place. The return value is always a params value that includes the new entries.
|
352
|
-
|
353
|
-
@function up.params.assign
|
354
|
-
@param {string|object|FormData|Array|undefined} params
|
355
|
-
@param {string|object|FormData|Array|undefined} otherParams
|
356
|
-
@return {string|object|FormData|Array}
|
357
|
-
@experimental
|
358
|
-
###
|
359
|
-
assign = (params, otherParams) ->
|
360
|
-
switch natureOf(params)
|
361
|
-
when NATURE_ARRAY
|
362
|
-
otherArray = toArray(otherParams)
|
363
|
-
params.push(otherArray...)
|
364
|
-
params
|
365
|
-
when NATURE_FORM_DATA
|
366
|
-
otherArray = toArray(otherParams)
|
367
|
-
for entry in otherArray
|
368
|
-
params.append(entry.name, entry.value)
|
369
|
-
params
|
370
|
-
when NATURE_OBJECT
|
371
|
-
u.assign(params, toObject(otherParams))
|
372
|
-
when NATURE_QUERY, NATURE_MISSING
|
373
|
-
# Strings and undefined are immutable, so we merge instead.
|
374
|
-
merge(params, otherParams)
|
375
|
-
|
376
|
-
submittingButton = (form) ->
|
377
|
-
$form = $(form)
|
378
|
-
submitButtonSelector = up.form.submitButtonSelector()
|
379
|
-
$activeElement = $(document.activeElement)
|
380
|
-
if $activeElement.is(submitButtonSelector) && $form.has($activeElement)
|
381
|
-
$activeElement[0]
|
382
|
-
else
|
383
|
-
# If no button is focused, we assume the first button in the form.
|
384
|
-
$form.find(submitButtonSelector)[0]
|
385
|
-
|
386
|
-
###**
|
387
|
-
Serializes request params from the given `<form>`.
|
388
|
-
|
389
|
-
The returned params may be passed as `{ params }` option to
|
390
|
-
[`up.request()`](/up.request) or [`up.replace()`](/up.replace).
|
391
|
-
|
392
|
-
The serialized params will include the form's submit button, if that
|
393
|
-
button as a `name` attribute.
|
394
|
-
|
395
|
-
\#\#\#\# Example
|
396
|
-
|
397
|
-
Given this HTML form:
|
398
|
-
|
399
|
-
<form>
|
400
|
-
<input type="text" name="name" value="Foo Bar">
|
401
|
-
<input type="text" name="email" value="foo@bar.com">
|
402
|
-
</form>
|
403
|
-
|
404
|
-
This would serialize the form into an array representation:
|
405
|
-
|
406
|
-
var params = up.params.fromForm('input[name=email]')
|
407
|
-
|
408
|
-
// params is now: [
|
409
|
-
// { name: 'name', value: 'Foo Bar' },
|
410
|
-
// { name: 'email', value: 'foo@bar.com' }
|
411
|
-
// ]
|
412
|
-
|
413
|
-
@function up.params.fromForm
|
414
|
-
@param {Element|jQuery|string} form
|
415
|
-
@return {Array}
|
416
|
-
@experimental
|
417
|
-
###
|
418
|
-
fromForm = (form) ->
|
419
|
-
if form = u.element(form)
|
420
|
-
fields = form.querySelectorAll(up.form.fieldSelector())
|
421
|
-
if button = submittingButton(form)
|
422
|
-
fields = u.toArray(fields)
|
423
|
-
fields.push(button)
|
424
|
-
return u.flatMap(fields, fromField)
|
425
|
-
|
426
|
-
###**
|
427
|
-
Serializes request params from a single [input field](/up.form.config#config.fields).
|
428
|
-
To serialize an entire form, use [`up.params.fromForm()`](/up.params.fromForm).
|
429
|
-
|
430
|
-
Note that some fields may produce multiple params, such as `<select multiple>`.
|
431
|
-
|
432
|
-
\#\#\#\# Example
|
433
|
-
|
434
|
-
Given this HTML form:
|
435
|
-
|
436
|
-
<form>
|
437
|
-
<input type="text" name="email" value="foo@bar.com">
|
438
|
-
<input type="password" name="password">
|
439
|
-
</form>
|
440
|
-
|
441
|
-
This would retrieve request parameters from the `email` field:
|
442
|
-
|
443
|
-
var params = up.params.fromField('input[name=email]')
|
444
|
-
|
445
|
-
// params is now: [{ name: 'email', value: 'foo@bar.com' }]
|
446
|
-
|
447
|
-
@function up.params.fromField
|
448
|
-
@param {Element|jQuery|string} form
|
449
|
-
@return {Array}
|
450
|
-
an array of `{ name, value }` objects
|
451
|
-
@experimental
|
452
|
-
###
|
453
|
-
fromField = (field) ->
|
454
|
-
params = []
|
455
|
-
if (field = u.element(field)) && (name = field.name) && (!field.disabled)
|
456
|
-
tagName = field.tagName
|
457
|
-
type = field.type
|
458
|
-
if tagName == 'SELECT'
|
459
|
-
for option in field.querySelectorAll('option')
|
460
|
-
if option.selected
|
461
|
-
params.push
|
462
|
-
name: name
|
463
|
-
value: option.value
|
464
|
-
else if type == 'checkbox' || type == 'radio'
|
465
|
-
if field.checked
|
466
|
-
params.push
|
467
|
-
name: name
|
468
|
-
value: field.value
|
469
|
-
else if type == 'file'
|
470
|
-
# The value of an input[type=file] is the local path displayed in the form.
|
471
|
-
# The actual File objects are in the #files property.
|
472
|
-
for file in field.files
|
473
|
-
params.push
|
474
|
-
name: name
|
475
|
-
value: file
|
476
|
-
else
|
477
|
-
params.push
|
478
|
-
name: name
|
479
|
-
value: field.value
|
480
|
-
params
|
481
|
-
|
482
|
-
###**
|
483
|
-
Returns the [query string](https://en.wikipedia.org/wiki/Query_string) from the given URL.
|
484
|
-
|
485
|
-
The query string is returned **without** a leading question mark (`?`).
|
486
|
-
Returns `undefined` if the given URL has no query component.
|
487
|
-
|
488
|
-
You can access individual values from the returned query string using functions like
|
489
|
-
[`up.params.get()`](/up.params.get) or [`up.params.toObject()`](/up.params.toObject).
|
490
|
-
|
491
|
-
\#\#\# Example
|
492
|
-
|
493
|
-
var query = up.params.fromURL('http://foo.com?bar=baz')
|
494
|
-
|
495
|
-
// query is now: 'bar=baz'
|
496
|
-
|
497
|
-
@function up.params.fromURL
|
498
|
-
@param {string} url
|
499
|
-
The URL from which to extract the query string.
|
500
|
-
@return {string|undefined}
|
501
|
-
The given URL's query string, or `undefined` if the URL has no query component.
|
502
|
-
@experimental
|
503
|
-
###
|
504
|
-
fromURL = (url) ->
|
505
|
-
urlParts = u.parseUrl(url)
|
506
|
-
if query = urlParts.search
|
507
|
-
query = query.replace(/^\?/, '')
|
508
|
-
query
|
509
|
-
|
510
|
-
toArray: toArray
|
511
|
-
toObject: toObject
|
512
|
-
toQuery: toQuery
|
513
|
-
toFormData: toFormData
|
514
|
-
buildURL: buildURL
|
515
|
-
get: get
|
516
|
-
add: add
|
517
|
-
assign: assign
|
518
|
-
merge: merge
|
519
|
-
fromForm: fromForm
|
520
|
-
fromURL: fromURL
|
521
|
-
|
522
|
-
)(jQuery)
|