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.
- 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
@@ -2,17 +2,16 @@
|
|
2
2
|
Toast alerts
|
3
3
|
============
|
4
4
|
|
5
|
-
@
|
5
|
+
@module up.toast
|
6
6
|
###
|
7
|
-
up.toast =
|
8
|
-
|
7
|
+
up.toast = do ->
|
9
8
|
u = up.util
|
10
|
-
|
9
|
+
e = up.element
|
11
10
|
|
12
11
|
VARIABLE_FORMATTER = (arg) -> "<span class='up-toast-variable'>#{u.escapeHtml(arg)}</span>"
|
13
12
|
|
14
|
-
state =
|
15
|
-
|
13
|
+
state = new up.Config
|
14
|
+
element: null
|
16
15
|
|
17
16
|
reset = ->
|
18
17
|
close()
|
@@ -21,39 +20,43 @@ up.toast = (($) ->
|
|
21
20
|
messageToHtml = (message) ->
|
22
21
|
if u.isArray(message)
|
23
22
|
message[0] = u.escapeHtml(message[0])
|
24
|
-
message =
|
23
|
+
message = up.log.sprintfWithFormattedArgs(VARIABLE_FORMATTER, message...)
|
25
24
|
else
|
26
25
|
message = u.escapeHtml(message)
|
27
26
|
message
|
28
27
|
|
29
28
|
isOpen = ->
|
30
|
-
!!state
|
29
|
+
!!state.element
|
31
30
|
|
32
|
-
addAction = (
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
addAction = (label, callback) ->
|
32
|
+
actions = state.element.querySelector('.up-toast-actions')
|
33
|
+
action = e.affix(actions, '.up-toast-action')
|
34
|
+
action.innerText = label
|
35
|
+
action.addEventListener('click', callback)
|
36
|
+
|
37
37
|
open = (message, options = {}) ->
|
38
38
|
close()
|
39
|
-
$toast = $('<div class="up-toast"></div>').prependTo('body')
|
40
|
-
$message = $('<div class="up-toast-message"></div>').appendTo($toast)
|
41
|
-
$actions = $('<div class="up-toast-actions"></div>').appendTo($toast)
|
42
39
|
|
43
40
|
message = messageToHtml(message)
|
44
|
-
|
41
|
+
|
42
|
+
state.element = e.createFromHtml """
|
43
|
+
<div class="up-toast">
|
44
|
+
<div class="up-toast-message">#{message}</div>
|
45
|
+
<div class="up-toast-actions"></div>
|
46
|
+
</div>
|
47
|
+
"""
|
45
48
|
|
46
49
|
if action = (options.action || options.inspect)
|
47
|
-
addAction(
|
50
|
+
addAction(action.label, action.callback)
|
48
51
|
|
49
|
-
addAction(
|
52
|
+
addAction('Close', close)
|
50
53
|
|
51
|
-
state
|
54
|
+
document.body.appendChild(state.element)
|
52
55
|
|
53
56
|
close = ->
|
54
57
|
if isOpen()
|
55
|
-
|
56
|
-
state
|
58
|
+
e.remove(state.element)
|
59
|
+
state.element = null
|
57
60
|
|
58
61
|
# The framework is reset between tests
|
59
62
|
up.on 'up:framework:reset', reset
|
@@ -62,5 +65,3 @@ up.toast = (($) ->
|
|
62
65
|
close: close
|
63
66
|
reset: reset
|
64
67
|
isOpen: isOpen
|
65
|
-
|
66
|
-
)(jQuery)
|
@@ -19,27 +19,36 @@ A gray triangle points to the element.
|
|
19
19
|
To change the styling, simply override the [CSS rules](https://github.com/unpoly/unpoly/blob/master/lib/assets/stylesheets/unpoly/tooltip.sass) for the `.up-tooltip` selector and its `:after`
|
20
20
|
selector that is used for the triangle.
|
21
21
|
|
22
|
-
The HTML of a tooltip element
|
22
|
+
The HTML of a tooltip element looks like this:
|
23
23
|
|
24
24
|
<div class="up-tooltip">
|
25
|
-
|
25
|
+
<div class="up-tooltip-content">
|
26
|
+
Tooltip text here
|
27
|
+
</div>
|
26
28
|
</div>
|
27
29
|
|
28
|
-
The tooltip element is appended to the
|
30
|
+
The tooltip element is appended to the [viewport](/up.viewport) of the anchor element.
|
29
31
|
|
30
|
-
@
|
32
|
+
@module up.tooltip
|
31
33
|
###
|
32
|
-
up.tooltip =
|
34
|
+
up.tooltip = do ->
|
33
35
|
|
34
36
|
u = up.util
|
37
|
+
e = up.element
|
35
38
|
|
36
39
|
###**
|
37
40
|
Configures defaults for future tooltips.
|
38
41
|
|
39
42
|
@property up.tooltip.config
|
40
43
|
@param {string} [config.position]
|
41
|
-
The default position of tooltips relative to the element.
|
42
|
-
|
44
|
+
The default position of tooltips relative to the opening element.
|
45
|
+
|
46
|
+
Valid values are `'top'`, `'right'`, `'bottom'` or `'left'`.
|
47
|
+
@param {string} [config.align]
|
48
|
+
Defines the alignment of the tooltip along its side.
|
49
|
+
|
50
|
+
When the tooltip's `{ position }` is `'top'` or `'bottom'`, valid `{ align }` values are `'left'`, `center'` and `'right'`.
|
51
|
+
When the tooltip's `{ position }` is `'left'` or `'right'`, valid `{ align }` values are `top'`, `center'` and `bottom'`.
|
43
52
|
@param {string} [config.openAnimation='fade-in']
|
44
53
|
The animation used to open a tooltip.
|
45
54
|
@param {string} [config.closeAnimation='fade-out']
|
@@ -54,8 +63,9 @@ up.tooltip = (($) ->
|
|
54
63
|
The timing function controlling the acceleration of the closing animation.
|
55
64
|
@stable
|
56
65
|
###
|
57
|
-
config =
|
66
|
+
config = new up.Config
|
58
67
|
position: 'top'
|
68
|
+
align: 'center'
|
59
69
|
openAnimation: 'fade-in'
|
60
70
|
closeAnimation: 'fade-out'
|
61
71
|
openDuration: 100
|
@@ -63,58 +73,45 @@ up.tooltip = (($) ->
|
|
63
73
|
openEasing: null
|
64
74
|
closeEasing: null
|
65
75
|
|
66
|
-
state =
|
76
|
+
state = new up.Config
|
67
77
|
phase: 'closed' # can be 'opening', 'opened', 'closing' and 'closed'
|
68
|
-
|
69
|
-
|
78
|
+
anchor: null # the element to which the tooltip is anchored
|
79
|
+
tooltip: null # the .up-tooltip element
|
80
|
+
content: null # the .up-tooltip-content element
|
81
|
+
tether: null # the up.Tether instance controlling the tooltip's position
|
70
82
|
position: null # the position of the tooltip element relative to its anchor
|
83
|
+
align: null
|
71
84
|
|
72
|
-
chain = new
|
85
|
+
chain = new up.DivertibleChain()
|
73
86
|
|
74
87
|
reset = ->
|
75
|
-
|
76
|
-
state.$tooltip?.remove()
|
88
|
+
state.tether?.destroy()
|
77
89
|
state.reset()
|
78
90
|
chain.reset()
|
79
91
|
config.reset()
|
80
92
|
|
81
|
-
|
82
|
-
|
83
|
-
|
93
|
+
createElement = (options) ->
|
94
|
+
state.tether = new up.Tether(u.only(state, 'anchor', 'position', 'align'))
|
95
|
+
state.tooltip = e.affix(state.tether.root, '.up-tooltip', 'up-position': state.position, 'up-align': state.align)
|
96
|
+
state.content = e.affix(state.tooltip, '.up-tooltip-content')
|
84
97
|
|
85
|
-
if
|
86
|
-
|
87
|
-
style.position = 'fixed'
|
98
|
+
if options.text
|
99
|
+
state.content.innerText = options.text
|
88
100
|
else
|
89
|
-
|
90
|
-
|
91
|
-
switch state.position
|
92
|
-
when 'top'
|
93
|
-
style.top = linkBox.top - tooltipBox.height
|
94
|
-
style.left = linkBox.left + 0.5 * (linkBox.width - tooltipBox.width)
|
95
|
-
when 'left'
|
96
|
-
style.top = linkBox.top + 0.5 * (linkBox.height - tooltipBox.height)
|
97
|
-
style.left = linkBox.left - tooltipBox.width
|
98
|
-
when 'right'
|
99
|
-
style.top = linkBox.top + 0.5 * (linkBox.height - tooltipBox.height)
|
100
|
-
style.left = linkBox.left + linkBox.width
|
101
|
-
when 'bottom'
|
102
|
-
style.top = linkBox.top + linkBox.height
|
103
|
-
style.left = linkBox.left + 0.5 * (linkBox.width - tooltipBox.width)
|
104
|
-
else
|
105
|
-
up.fail("Unknown position option '%s'", state.position)
|
106
|
-
|
107
|
-
state.$tooltip.attr('up-position', state.position)
|
108
|
-
u.writeInlineStyle(state.$tooltip, style)
|
101
|
+
state.content.innerHTML = options.html
|
109
102
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
103
|
+
###**
|
104
|
+
Forces the tooltip to update its position relative to its anchor element.
|
105
|
+
|
106
|
+
Unpoly will automatically keep tooltips aligned when
|
107
|
+
the document is resized or scrolled. Complex layout changes may make
|
108
|
+
it necessary to call this function.
|
109
|
+
|
110
|
+
@function up.tooltip.sync
|
111
|
+
@experimental
|
112
|
+
###
|
113
|
+
syncPosition = ->
|
114
|
+
state.tether?.sync()
|
118
115
|
|
119
116
|
###**
|
120
117
|
Opens a tooltip over the given element.
|
@@ -125,9 +122,7 @@ up.tooltip = (($) ->
|
|
125
122
|
|
126
123
|
In order to attach a tooltip to a `<span class="help">?</span>`:
|
127
124
|
|
128
|
-
up.tooltip.attach('.help', {
|
129
|
-
text: 'Enter multiple words or phrases'
|
130
|
-
});
|
125
|
+
up.tooltip.attach('.help', { text: 'Useful info' })
|
131
126
|
|
132
127
|
@function up.tooltip.attach
|
133
128
|
@param {Element|jQuery|string} elementOrSelector
|
@@ -141,33 +136,40 @@ up.tooltip = (($) ->
|
|
141
136
|
|
142
137
|
Make sure to escape any user-provided text before passing it as this option,
|
143
138
|
or use `options.text` (which automatically escapes).
|
144
|
-
@param {string} [options.position
|
145
|
-
The position
|
146
|
-
|
139
|
+
@param {string} [options.position]
|
140
|
+
The tooltip's position relative to the opening element.
|
141
|
+
|
142
|
+
Valid values are `'top'`, `'right'`, `'bottom'` or `'left'`.
|
143
|
+
@param {string} [options.align]
|
144
|
+
Defines the alignment of the tooltip along its side.
|
145
|
+
|
146
|
+
When the tooltip's `{ position }` is `'top'` or `'bottom'`, valid `{ align }` values are `'left'`, `center'` and `'right'`.
|
147
|
+
When the tooltip's `{ position }` is `'left'` or `'right'`, valid `{ align }` values are `top'`, `center'` and `bottom'`.
|
147
148
|
@param {string} [options.animation]
|
148
149
|
The [animation](/up.motion) to use when opening the tooltip.
|
149
150
|
@return {Promise}
|
150
151
|
A promise that will be fulfilled when the tooltip's opening animation has finished.
|
151
152
|
@stable
|
152
153
|
###
|
153
|
-
attachAsap = (elementOrSelector, options
|
154
|
+
attachAsap = (elementOrSelector, options) ->
|
154
155
|
chain.asap closeNow, (-> attachNow(elementOrSelector, options))
|
155
156
|
|
156
|
-
attachNow = (elementOrSelector, options) ->
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
animation =
|
163
|
-
animateOptions = up.motion.animateOptions(options,
|
157
|
+
attachNow = (elementOrSelector, options = {}) ->
|
158
|
+
anchor = e.get(elementOrSelector)
|
159
|
+
html = options.html ? anchor.getAttribute('up-tooltip-html')
|
160
|
+
text = options.text ? anchor.getAttribute('up-tooltip')
|
161
|
+
position = options.position ? anchor.getAttribute('up-position') ? config.position
|
162
|
+
align = options.align ? anchor.getAttribute('up-align') ? config.align
|
163
|
+
animation = options.animation ? e.booleanOrStringAttr(anchor, 'up-animation') ? config.openAnimation
|
164
|
+
animateOptions = up.motion.animateOptions(options, anchor, duration: config.openDuration, easing: config.openEasing)
|
164
165
|
|
165
166
|
state.phase = 'opening'
|
166
|
-
state
|
167
|
-
createElement(text: text, html: html)
|
167
|
+
state.anchor = anchor
|
168
168
|
state.position = position
|
169
|
-
align
|
170
|
-
|
169
|
+
state.align = align
|
170
|
+
createElement({ text, html })
|
171
|
+
syncPosition()
|
172
|
+
up.animate(state.tooltip, animation, animateOptions).then ->
|
171
173
|
state.phase = 'opened'
|
172
174
|
|
173
175
|
###**
|
@@ -193,10 +195,13 @@ up.tooltip = (($) ->
|
|
193
195
|
animateOptions = up.motion.animateOptions(options, duration: config.closeDuration, easing: config.closeEasing)
|
194
196
|
u.assign(options, animateOptions)
|
195
197
|
state.phase = 'closing'
|
196
|
-
up.destroy(state
|
198
|
+
up.destroy(state.tooltip, options).then ->
|
197
199
|
state.phase = 'closed'
|
198
|
-
state
|
199
|
-
state
|
200
|
+
state.tether.destroy()
|
201
|
+
state.tether = null
|
202
|
+
state.tooltip = null
|
203
|
+
state.content = null
|
204
|
+
state.anchor = null
|
200
205
|
|
201
206
|
###**
|
202
207
|
Returns whether a tooltip is currently showing.
|
@@ -224,9 +229,14 @@ up.tooltip = (($) ->
|
|
224
229
|
The animation used to open the tooltip.
|
225
230
|
Defaults to [`up.tooltip.config.openAnimation`](/up.tooltip.config).
|
226
231
|
@param {string} [up-position]
|
227
|
-
The
|
228
|
-
|
229
|
-
|
232
|
+
The tooltip's position relative to the opening element.
|
233
|
+
|
234
|
+
Valid values are `'top'`, `'right'`, `'bottom'` or `'left'`.
|
235
|
+
@param {string} [up-align]
|
236
|
+
Defines the alignment of the tooltip along its side.
|
237
|
+
|
238
|
+
When the tooltip's `{ position }` is `'top'` or `'bottom'`, valid `{ align }` values are `'left'`, `center'` and `'right'`.
|
239
|
+
When the tooltip's `{ position }` is `'left'` or `'right'`, valid `{ align }` values are `top'`, `center'` and `bottom'`.
|
230
240
|
@stable
|
231
241
|
###
|
232
242
|
|
@@ -238,16 +248,16 @@ up.tooltip = (($) ->
|
|
238
248
|
@selector [up-tooltip-html]
|
239
249
|
@stable
|
240
250
|
###
|
241
|
-
up.compiler '[up-tooltip], [up-tooltip-html]', (
|
251
|
+
up.compiler '[up-tooltip], [up-tooltip-html]', (opener) ->
|
242
252
|
# Don't register these events on document since *every*
|
243
253
|
# mouse move interaction bubbles up to the document.
|
244
|
-
|
245
|
-
|
254
|
+
opener.addEventListener 'mouseenter', -> attachAsap(opener)
|
255
|
+
opener.addEventListener 'mouseleave', -> closeAsap()
|
246
256
|
|
247
257
|
# We close the tooltip when someone clicks on the document.
|
248
258
|
# We also need to listen to up:action:consumed in case an [up-instant] link
|
249
259
|
# was followed on mousedown.
|
250
|
-
up.on 'click up:action:consumed', (
|
260
|
+
up.on 'click up:action:consumed', (_event) -> # do take an argument so we won't parse [up-data]
|
251
261
|
closeAsap()
|
252
262
|
# Do not halt the event chain here. The user is allowed to directly activate
|
253
263
|
# a link in the background, even with a (now closing) tooltip open.
|
@@ -256,11 +266,11 @@ up.tooltip = (($) ->
|
|
256
266
|
up.on 'up:framework:reset', reset
|
257
267
|
|
258
268
|
# Close the tooltip when the user presses ESC.
|
259
|
-
up.
|
269
|
+
up.event.onEscape(-> closeAsap())
|
260
270
|
|
261
271
|
config: config
|
262
272
|
attach: attachAsap
|
263
273
|
isOpen: isOpen
|
264
274
|
close: closeAsap
|
275
|
+
sync: syncPosition
|
265
276
|
|
266
|
-
)(jQuery)
|
@@ -1,13 +1,17 @@
|
|
1
1
|
###**
|
2
2
|
Utility functions
|
3
3
|
=================
|
4
|
-
|
5
|
-
Unpoly comes with a number of utility functions
|
6
|
-
that might save you from loading something like [Lodash](https://lodash.com/).
|
7
4
|
|
8
|
-
|
5
|
+
The `up.util` module contains functions to facilitate the work with basic JavaScript
|
6
|
+
values like lists, strings or functions.
|
7
|
+
|
8
|
+
You will recognize many functions form other utility libraries like [Lodash](https://lodash.com/).
|
9
|
+
While feature parity with Lodash is not a goal of `up.util`, you might find it sufficient
|
10
|
+
to not include another library in your asset bundle.
|
11
|
+
|
12
|
+
@module up.util
|
9
13
|
###
|
10
|
-
up.util =
|
14
|
+
up.util = do ->
|
11
15
|
|
12
16
|
###**
|
13
17
|
A function that does nothing.
|
@@ -75,10 +79,6 @@ up.util = (($) ->
|
|
75
79
|
normalized = parts.protocol + "//" + parts.hostname
|
76
80
|
normalized += ":#{parts.port}" unless isStandardPort(parts.protocol, parts.port)
|
77
81
|
pathname = parts.pathname
|
78
|
-
# Some IEs don't include a leading slash in the #pathname property.
|
79
|
-
# We have seen this in IE11 and W3Schools claims it happens in IE9 or earlier
|
80
|
-
# http://www.w3schools.com/jsref/prop_anchor_pathname.asp
|
81
|
-
pathname = "/#{pathname}" unless pathname[0] == '/'
|
82
82
|
pathname = pathname.replace(/\/$/, '') if options?.stripTrailingSlash == true
|
83
83
|
normalized += pathname
|
84
84
|
normalized += parts.search unless options?.search == false
|
@@ -88,7 +88,7 @@ up.util = (($) ->
|
|
88
88
|
isCrossDomain = (targetUrl) ->
|
89
89
|
currentUrl = parseUrl(location.href)
|
90
90
|
targetUrl = parseUrl(targetUrl)
|
91
|
-
currentUrl.protocol != targetUrl.protocol || currentUrl.
|
91
|
+
currentUrl.protocol != targetUrl.protocol || currentUrl.hostname != targetUrl.hostname
|
92
92
|
|
93
93
|
###**
|
94
94
|
Parses the given URL into components such as hostname and path.
|
@@ -101,24 +101,33 @@ up.util = (($) ->
|
|
101
101
|
The parsed URL as an object with
|
102
102
|
`protocol`, `hostname`, `port`, `pathname`, `search` and `hash`
|
103
103
|
properties.
|
104
|
-
@
|
104
|
+
@stable
|
105
105
|
###
|
106
|
-
parseUrl = (
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
parseUrl = (urlOrLink) ->
|
107
|
+
if isJQuery(urlOrLink)
|
108
|
+
# In case someone passed us a $link, unwrap it
|
109
|
+
link = up.element.get(urlOrLink)
|
110
|
+
else if urlOrLink.pathname
|
111
|
+
# If we are handed a parsed URL, just return it
|
112
|
+
link = urlOrLink
|
113
|
+
else
|
114
|
+
link = document.createElement('a')
|
115
|
+
link.href = urlOrLink
|
110
116
|
|
111
|
-
#
|
112
|
-
|
113
|
-
|
117
|
+
# In IE11 the #hostname and #port properties of unqualified URLs are empty strings.
|
118
|
+
# We can fix this by setting the link's { href } on the link itself.
|
119
|
+
unless link.hostname
|
120
|
+
link.href = link.href
|
114
121
|
|
115
|
-
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
+
# Some IEs don't include a leading slash in the #pathname property.
|
123
|
+
# We have confirmed this in IE11 and earlier.
|
124
|
+
unless link.pathname[0] == '/'
|
125
|
+
# Only copy the link into an object when we need to (to change a property).
|
126
|
+
# Note that we're parsing a lot of URLs for [up-active].
|
127
|
+
link = only(link, 'protocol', 'hostname', 'port', 'pathname', 'search', 'hash')
|
128
|
+
link.pathname = '/' + link.pathname
|
129
|
+
|
130
|
+
link
|
122
131
|
|
123
132
|
###**
|
124
133
|
@function up.util.normalizeMethod
|
@@ -137,122 +146,6 @@ up.util = (($) ->
|
|
137
146
|
methodAllowsPayload = (method) ->
|
138
147
|
method != 'GET' && method != 'HEAD'
|
139
148
|
|
140
|
-
###**
|
141
|
-
@function $createElementFromSelector
|
142
|
-
@internal
|
143
|
-
###
|
144
|
-
$createElementFromSelector = (selector) ->
|
145
|
-
path = selector.split(/[ >]/)
|
146
|
-
$root = null
|
147
|
-
for depthSelector, iteration in path
|
148
|
-
conjunction = depthSelector.match(/(^|\.|\#)[A-Za-z0-9\-_]+/g)
|
149
|
-
tag = "div"
|
150
|
-
classes = []
|
151
|
-
id = null
|
152
|
-
for expression in conjunction
|
153
|
-
switch expression[0]
|
154
|
-
when "."
|
155
|
-
classes.push expression.substr(1)
|
156
|
-
when "#"
|
157
|
-
id = expression.substr(1)
|
158
|
-
else
|
159
|
-
tag = expression
|
160
|
-
html = "<" + tag
|
161
|
-
html += " class=\"" + classes.join(" ") + "\"" if classes.length
|
162
|
-
html += " id=\"" + id + "\"" if id
|
163
|
-
html += ">"
|
164
|
-
$element = $(html)
|
165
|
-
$element.appendTo($parent) if $parent
|
166
|
-
$root = $element if iteration == 0
|
167
|
-
$parent = $element
|
168
|
-
$root
|
169
|
-
|
170
|
-
###**
|
171
|
-
@function $createPlaceHolder
|
172
|
-
@internal
|
173
|
-
###
|
174
|
-
$createPlaceholder = (selector, container = document.body) ->
|
175
|
-
$placeholder = $createElementFromSelector(selector)
|
176
|
-
$placeholder.addClass('up-placeholder')
|
177
|
-
$placeholder.appendTo(container)
|
178
|
-
$placeholder
|
179
|
-
|
180
|
-
###**
|
181
|
-
Returns a CSS selector that matches the given element as good as possible.
|
182
|
-
|
183
|
-
This uses, in decreasing order of priority:
|
184
|
-
|
185
|
-
- The element's `up-id` attribute
|
186
|
-
- The element's ID
|
187
|
-
- The element's name
|
188
|
-
- The element's classes
|
189
|
-
- The element's tag names
|
190
|
-
|
191
|
-
@function up.util.selectorForElement
|
192
|
-
@param {string|Element|jQuery}
|
193
|
-
The element for which to create a selector.
|
194
|
-
@experimental
|
195
|
-
###
|
196
|
-
selectorForElement = (element) ->
|
197
|
-
$element = $(element)
|
198
|
-
selector = undefined
|
199
|
-
|
200
|
-
if isSingletonElement($element)
|
201
|
-
selector = elementTagName($element)
|
202
|
-
else if upId = presence($element.attr("up-id"))
|
203
|
-
selector = attributeSelector('up-id', upId)
|
204
|
-
else if id = presence($element.attr("id"))
|
205
|
-
if id.match(/^[a-z0-9\-_]+$/i)
|
206
|
-
selector = "##{id}"
|
207
|
-
else
|
208
|
-
selector = attributeSelector('id', id)
|
209
|
-
else if name = presence($element.attr("name"))
|
210
|
-
selector = elementTagName($element) + attributeSelector('name', name)
|
211
|
-
else if classes = presence(nonUpClasses($element))
|
212
|
-
selector = ''
|
213
|
-
for klass in classes
|
214
|
-
selector += ".#{klass}"
|
215
|
-
else if ariaLabel = presence($element.attr("aria-label"))
|
216
|
-
selector = attributeSelector('aria-label', ariaLabel)
|
217
|
-
else
|
218
|
-
selector = elementTagName($element)
|
219
|
-
|
220
|
-
return selector
|
221
|
-
|
222
|
-
isSingletonElement = ($element) ->
|
223
|
-
# jQuery's is() returns true if at least one element
|
224
|
-
# in the collection matches the selector
|
225
|
-
$element.is('html, body, head, title')
|
226
|
-
|
227
|
-
# isGoodSelector = (selector) ->
|
228
|
-
# selector.indexOf('#') >= -1 || selector.indexOf('[') >= -1
|
229
|
-
|
230
|
-
# defineMemoizedGetter = (obj, property, fetchFn) ->
|
231
|
-
# cacheProperty = "_#{property}Cache"
|
232
|
-
# Object.defineProperty methods, property,
|
233
|
-
# get: ->
|
234
|
-
# @[cacheProperty] ||= [fetchFn(this)]
|
235
|
-
# @[cacheProperty][0]
|
236
|
-
|
237
|
-
elementTagName = ($element) ->
|
238
|
-
$element.prop('tagName').toLowerCase()
|
239
|
-
|
240
|
-
attributeSelector = (attribute, value) ->
|
241
|
-
value = value.replace(/"/g, '\\"')
|
242
|
-
"[#{attribute}=\"#{value}\"]"
|
243
|
-
|
244
|
-
nonUpClasses = ($element) ->
|
245
|
-
classString = $element.attr('class') || ''
|
246
|
-
classes = splitValues(classString)
|
247
|
-
reject classes, (klass) -> klass.match(/^up-/)
|
248
|
-
|
249
|
-
# jQuery's implementation of $(...) cannot create elements that have
|
250
|
-
# an <html> or <body> tag. So we're using native elements.
|
251
|
-
# Also IE9 cannot set innerHTML on a <html> or <head> element.
|
252
|
-
createElementFromHtml = (html) ->
|
253
|
-
parser = new DOMParser()
|
254
|
-
parser.parseFromString(html, 'text/html')
|
255
|
-
|
256
149
|
assignPolyfill = (target, sources...) ->
|
257
150
|
for source in sources
|
258
151
|
for own key, value of source
|
@@ -278,23 +171,11 @@ up.util = (($) ->
|
|
278
171
|
@function up.util.values
|
279
172
|
@param {Object} object
|
280
173
|
@return {Array<string>}
|
281
|
-
@experimental
|
282
|
-
###
|
283
|
-
objectValues = Object.values || valuesPolyfill
|
284
|
-
|
285
|
-
###**
|
286
|
-
Returns a new string with whitespace removed from the beginning
|
287
|
-
and end of the given string.
|
288
|
-
|
289
|
-
@param {string}
|
290
|
-
A string that might have whitespace at the beginning and end.
|
291
|
-
@return {string}
|
292
|
-
The trimmed string.
|
293
174
|
@stable
|
294
175
|
###
|
295
|
-
|
176
|
+
objectValues = Object.values || valuesPolyfill
|
296
177
|
|
297
|
-
|
178
|
+
iteratee = (block) ->
|
298
179
|
if isString(block)
|
299
180
|
(item) -> item[block]
|
300
181
|
else
|
@@ -304,8 +185,8 @@ up.util = (($) ->
|
|
304
185
|
Translate all items in an array to new array of items.
|
305
186
|
|
306
187
|
@function up.util.map
|
307
|
-
@param {Array
|
308
|
-
@param {Function(
|
188
|
+
@param {Array} array
|
189
|
+
@param {Function(element, index): any|String} block
|
309
190
|
A function that will be called with each element and (optional) iteration index.
|
310
191
|
|
311
192
|
You can also pass a property name as a String,
|
@@ -316,17 +197,27 @@ up.util = (($) ->
|
|
316
197
|
###
|
317
198
|
map = (array, block) ->
|
318
199
|
return [] if array.length == 0
|
319
|
-
block =
|
200
|
+
block = iteratee(block)
|
320
201
|
for item, index in array
|
321
202
|
block(item, index)
|
322
203
|
|
204
|
+
###**
|
205
|
+
@function up.util.mapObject
|
206
|
+
@internal
|
207
|
+
###
|
208
|
+
mapObject = (array, pairer) ->
|
209
|
+
merger = (object, pair) ->
|
210
|
+
object[pair[0]] = pair[1]
|
211
|
+
return object
|
212
|
+
map(array, pairer).reduce(merger, {})
|
213
|
+
|
323
214
|
###**
|
324
215
|
Calls the given function for each element (and, optional, index)
|
325
216
|
of the given array.
|
326
217
|
|
327
218
|
@function up.util.each
|
328
|
-
@param {Array
|
329
|
-
@param {Function(
|
219
|
+
@param {Array} array
|
220
|
+
@param {Function(element, index)} block
|
330
221
|
A function that will be called with each element and (optional) iteration index.
|
331
222
|
@stable
|
332
223
|
###
|
@@ -341,7 +232,7 @@ up.util = (($) ->
|
|
341
232
|
|
342
233
|
@function up.util.times
|
343
234
|
@param {number} count
|
344
|
-
@param {Function} block
|
235
|
+
@param {Function()} block
|
345
236
|
@stable
|
346
237
|
###
|
347
238
|
times = (count, block) ->
|
@@ -416,41 +307,91 @@ up.util = (($) ->
|
|
416
307
|
###**
|
417
308
|
Return whether the given argument is considered to be blank.
|
418
309
|
|
419
|
-
|
310
|
+
By default, this function returns `true` for:
|
420
311
|
|
421
312
|
- `undefined`
|
422
313
|
- `null`
|
423
314
|
- Empty strings
|
424
315
|
- Empty arrays
|
425
|
-
-
|
316
|
+
- A plain object without own enumerable properties
|
426
317
|
|
427
318
|
All other arguments return `false`.
|
428
319
|
|
320
|
+
To check implement blank-ness checks for user-defined classes,
|
321
|
+
see `up.util.isBlank.key`.
|
322
|
+
|
429
323
|
@function up.util.isBlank
|
430
|
-
@param
|
324
|
+
@param value
|
325
|
+
The value is to check.
|
431
326
|
@return {boolean}
|
327
|
+
Whether the value is blank.
|
432
328
|
@stable
|
433
329
|
###
|
434
|
-
isBlank = (
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
330
|
+
isBlank = (value) ->
|
331
|
+
if isMissing(value)
|
332
|
+
return true
|
333
|
+
if isObject(value) && value[isBlank.key]
|
334
|
+
return value[isBlank.key]()
|
335
|
+
if isString(value) || isList(value)
|
336
|
+
return value.length == 0
|
337
|
+
if isOptions(value)
|
338
|
+
return Object.keys(value).length == 0
|
439
339
|
return false
|
440
340
|
|
341
|
+
###**
|
342
|
+
This property contains the name of a method that user-defined classes
|
343
|
+
may implement to hook into the `up.util.isBlank()` protocol.
|
344
|
+
|
345
|
+
\#\#\# Example
|
346
|
+
|
347
|
+
We have a user-defined `Account` class that we want to use with `up.util.isBlank()`:
|
348
|
+
|
349
|
+
```
|
350
|
+
class Account {
|
351
|
+
constructor(email) {
|
352
|
+
this.email = email
|
353
|
+
}
|
354
|
+
|
355
|
+
[up.util.isBlank.key]() {
|
356
|
+
return up.util.isBlank(this.email)
|
357
|
+
}
|
358
|
+
}
|
359
|
+
```
|
360
|
+
|
361
|
+
Note that the protocol method is not actually named `'up.util.isBlank.key'`.
|
362
|
+
Instead it is named after the *value* of the `up.util.isBlank.key` property.
|
363
|
+
To do so, the code sample above is using a
|
364
|
+
[computed property name](https://medium.com/front-end-weekly/javascript-object-creation-356e504173a8)
|
365
|
+
in square brackets.
|
366
|
+
|
367
|
+
We may now use `Account` instances with `up.util.isBlank()`:
|
368
|
+
|
369
|
+
```
|
370
|
+
foo = new Account('foo@foo.com')
|
371
|
+
bar = new Account('')
|
372
|
+
|
373
|
+
console.log(up.util.isBlank(foo)) // prints false
|
374
|
+
console.log(up.util.isBlank(bar)) // prints true
|
375
|
+
```
|
376
|
+
|
377
|
+
@property up.util.isBlank.key
|
378
|
+
@experimental
|
379
|
+
###
|
380
|
+
isBlank.key = 'up.util.isBlank'
|
381
|
+
|
441
382
|
###**
|
442
383
|
Returns the given argument if the argument is [present](/up.util.isPresent),
|
443
384
|
otherwise returns `undefined`.
|
444
385
|
|
445
386
|
@function up.util.presence
|
446
|
-
@param
|
447
|
-
@param {Function(
|
387
|
+
@param value
|
388
|
+
@param {Function(value): boolean} [tester=up.util.isPresent]
|
448
389
|
The function that will be used to test whether the argument is present.
|
449
|
-
@return {
|
390
|
+
@return {any|undefined}
|
450
391
|
@stable
|
451
392
|
###
|
452
|
-
presence = (
|
453
|
-
if tester(
|
393
|
+
presence = (value, tester = isPresent) ->
|
394
|
+
if tester(value) then value else undefined
|
454
395
|
|
455
396
|
###**
|
456
397
|
Returns whether the given argument is not [blank](/up.util.isBlank).
|
@@ -491,7 +432,7 @@ up.util = (($) ->
|
|
491
432
|
@function up.util.isBoolean
|
492
433
|
@param object
|
493
434
|
@return {boolean}
|
494
|
-
@
|
435
|
+
@stable
|
495
436
|
###
|
496
437
|
isBoolean = (object) ->
|
497
438
|
typeof(object) == 'boolean' || object instanceof Boolean
|
@@ -539,7 +480,7 @@ up.util = (($) ->
|
|
539
480
|
(typeOfResult == 'object' && !isNull(object)) || typeOfResult == 'function'
|
540
481
|
|
541
482
|
###**
|
542
|
-
Returns whether the given argument is a DOM element.
|
483
|
+
Returns whether the given argument is a [DOM element](https://developer.mozilla.org/de/docs/Web/API/Element).
|
543
484
|
|
544
485
|
@function up.util.isElement
|
545
486
|
@param object
|
@@ -547,10 +488,10 @@ up.util = (($) ->
|
|
547
488
|
@stable
|
548
489
|
###
|
549
490
|
isElement = (object) ->
|
550
|
-
|
491
|
+
object instanceof Element
|
551
492
|
|
552
493
|
###**
|
553
|
-
Returns whether the given argument is a jQuery collection.
|
494
|
+
Returns whether the given argument is a [jQuery collection](https://learn.jquery.com/using-jquery-core/jquery-object/).
|
554
495
|
|
555
496
|
@function up.util.isJQuery
|
556
497
|
@param object
|
@@ -558,7 +499,7 @@ up.util = (($) ->
|
|
558
499
|
@stable
|
559
500
|
###
|
560
501
|
isJQuery = (object) ->
|
561
|
-
object instanceof jQuery
|
502
|
+
up.browser.canJQuery() && (object instanceof jQuery)
|
562
503
|
|
563
504
|
###**
|
564
505
|
Returns whether the given argument is an object with a `then` method.
|
@@ -596,66 +537,183 @@ up.util = (($) ->
|
|
596
537
|
object instanceof FormData
|
597
538
|
|
598
539
|
###**
|
599
|
-
Converts the given array-like
|
540
|
+
Converts the given [array-like value](/up.util.isList) into an array.
|
600
541
|
|
601
|
-
|
542
|
+
If the given value is already an array, it is returned unchanged.
|
602
543
|
|
603
544
|
@function up.util.toArray
|
604
545
|
@param object
|
605
546
|
@return {Array}
|
606
547
|
@stable
|
607
548
|
###
|
608
|
-
toArray = (
|
609
|
-
|
549
|
+
toArray = (value) ->
|
550
|
+
if isArray(value)
|
551
|
+
value
|
552
|
+
else
|
553
|
+
Array.prototype.slice.call(value)
|
554
|
+
|
555
|
+
###***
|
556
|
+
Returns whether the given argument is an array-like value.
|
557
|
+
|
558
|
+
Return true for `Array`, a
|
559
|
+
[`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList),
|
560
|
+
the [arguments object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)
|
561
|
+
or a jQuery collection.
|
562
|
+
|
563
|
+
Use [`up.util.isArray()`](/up.util.isArray) to test whether a value is an actual `Array`.
|
564
|
+
|
565
|
+
@function up.util.isList
|
566
|
+
@param value
|
567
|
+
@return {Boolean}
|
568
|
+
@experimental
|
569
|
+
###
|
570
|
+
isList = (value) ->
|
571
|
+
isArray(value) ||
|
572
|
+
isNodeList(value) ||
|
573
|
+
isArguments(value) ||
|
574
|
+
isJQuery(value) ||
|
575
|
+
isHTMLCollection(value)
|
610
576
|
|
611
577
|
###**
|
612
|
-
Returns
|
578
|
+
Returns whether the given value is a [`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList).
|
613
579
|
|
614
|
-
|
615
|
-
|
616
|
-
@
|
617
|
-
@
|
580
|
+
`NodeLists` are array-like objects returned by [`document.querySelectorAll()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll).
|
581
|
+
|
582
|
+
@function up.util.isNodeList
|
583
|
+
@param value
|
584
|
+
@return {Boolean}
|
585
|
+
@internal
|
618
586
|
###
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
object = assign({}, object)
|
625
|
-
# copied = true
|
626
|
-
# if copied && deep
|
627
|
-
# for key, value of object
|
628
|
-
# object[key] = copy(value, true)
|
629
|
-
object
|
587
|
+
isNodeList = (value) ->
|
588
|
+
value instanceof NodeList
|
589
|
+
|
590
|
+
isHTMLCollection = (value) ->
|
591
|
+
value instanceof HTMLCollection
|
630
592
|
|
631
593
|
# ###**
|
632
|
-
# Returns
|
594
|
+
# Returns whether the given value is an [`HTMLCollection`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection).
|
633
595
|
#
|
634
|
-
# @function up.util.
|
635
|
-
# @param
|
636
|
-
# @return {
|
637
|
-
# @
|
596
|
+
# @function up.util.isHtmlCollection
|
597
|
+
# @param value
|
598
|
+
# @return {Boolean}
|
599
|
+
# @experimental
|
638
600
|
# ###
|
639
|
-
#
|
640
|
-
#
|
601
|
+
# isHtmlCollection = (value) ->
|
602
|
+
# value instanceof HTMLCollection
|
641
603
|
|
642
604
|
###**
|
643
|
-
|
644
|
-
If given a string, returns the first element matching that string.
|
645
|
-
If given any other argument, returns the argument unchanged.
|
605
|
+
Returns whether the given value is an [arguments object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments).
|
646
606
|
|
647
|
-
@function up.util.
|
648
|
-
@param
|
649
|
-
@return {
|
607
|
+
@function up.util.isArguments
|
608
|
+
@param value
|
609
|
+
@return {Boolean}
|
650
610
|
@internal
|
651
611
|
###
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
612
|
+
isArguments = (value) ->
|
613
|
+
Object.prototype.toString.call(value) == '[object Arguments]'
|
614
|
+
|
615
|
+
###**
|
616
|
+
@function up.util.wrapList
|
617
|
+
@return {Array|NodeList|jQuery}
|
618
|
+
@internal
|
619
|
+
###
|
620
|
+
wrapList = (value) ->
|
621
|
+
if isList(value)
|
622
|
+
value
|
623
|
+
else if isMissing(value)
|
624
|
+
[]
|
657
625
|
else
|
658
|
-
|
626
|
+
[value]
|
627
|
+
|
628
|
+
###**
|
629
|
+
Returns a shallow copy of the given value.
|
630
|
+
|
631
|
+
\#\#\# Copying protocol
|
632
|
+
|
633
|
+
- By default `up.util.copy()` can copy [array-like values](/up.util.isList),
|
634
|
+
plain objects and `Date` instances.
|
635
|
+
- Array-like objects are copied into new arrays.
|
636
|
+
- Unsupported types of values are returned unchanged.
|
637
|
+
- To make the copying protocol work with user-defined class,
|
638
|
+
see `up.util.copy.key`.
|
639
|
+
- Immutable objects, like strings or numbers, do not need to be copied.
|
640
|
+
|
641
|
+
@function up.util.copy
|
642
|
+
@param {any} object
|
643
|
+
@return {any}
|
644
|
+
@stable
|
645
|
+
###
|
646
|
+
copy = (value, deep) ->
|
647
|
+
if isObject(value) && value[copy.key]
|
648
|
+
value = value[copy.key]()
|
649
|
+
else if isList(value)
|
650
|
+
value = Array.prototype.slice.call(value)
|
651
|
+
copied = true
|
652
|
+
else if isOptions(value)
|
653
|
+
value = assign({}, value)
|
654
|
+
copied = true
|
655
|
+
if copied && deep
|
656
|
+
for k, v of value
|
657
|
+
value[k] = copy(v, true)
|
658
|
+
value
|
659
|
+
|
660
|
+
###**
|
661
|
+
This property contains the name of a method that user-defined classes
|
662
|
+
may implement to hook into the `up.util.copy()` protocol.
|
663
|
+
|
664
|
+
\#\#\# Example
|
665
|
+
|
666
|
+
We have a user-defined `Account` class that we want to use with `up.util.copy()`:
|
667
|
+
|
668
|
+
```
|
669
|
+
class Account {
|
670
|
+
constructor(email) {
|
671
|
+
this.email = email
|
672
|
+
}
|
673
|
+
|
674
|
+
[up.util.copy.key]() {
|
675
|
+
return new Account(this.email)
|
676
|
+
}
|
677
|
+
}
|
678
|
+
```
|
679
|
+
|
680
|
+
Note that the protocol method is not actually named `'up.util.copy.key'`.
|
681
|
+
Instead it is named after the *value* of the `up.util.copy.key` property.
|
682
|
+
To do so, the code sample above is using a
|
683
|
+
[computed property name](https://medium.com/front-end-weekly/javascript-object-creation-356e504173a8)
|
684
|
+
in square brackets.
|
685
|
+
|
686
|
+
We may now use `Account` instances with `up.util.copy()`:
|
687
|
+
|
688
|
+
```
|
689
|
+
original = new User('foo@foo.com')
|
690
|
+
|
691
|
+
copy = up.util.copy(original)
|
692
|
+
console.log(copy.email) // prints 'foo@foo.com'
|
693
|
+
|
694
|
+
original.email = 'bar@bar.com' // change the original
|
695
|
+
console.log(copy.email) // still prints 'foo@foo.com'
|
696
|
+
```
|
697
|
+
|
698
|
+
@property up.util.copy.key
|
699
|
+
@param {string} key
|
700
|
+
@experimental
|
701
|
+
###
|
702
|
+
copy.key = 'up.util.copy'
|
703
|
+
|
704
|
+
# Implement up.util.copy protocol for Date
|
705
|
+
Date.prototype[copy.key] = -> new Date(+@)
|
706
|
+
|
707
|
+
###**
|
708
|
+
Returns a deep copy of the given array or object.
|
709
|
+
|
710
|
+
@function up.util.deepCopy
|
711
|
+
@param {Object|Array} object
|
712
|
+
@return {Object|Array}
|
713
|
+
@internal
|
714
|
+
###
|
715
|
+
deepCopy = (object) ->
|
716
|
+
copy(object, true)
|
659
717
|
|
660
718
|
###**
|
661
719
|
Creates a new object by merging together the properties from the given objects.
|
@@ -716,34 +774,20 @@ up.util = (($) ->
|
|
716
774
|
{}
|
717
775
|
|
718
776
|
###**
|
719
|
-
|
720
|
-
|
721
|
-
This function is useful when you have multiple option sources and the value can be boolean.
|
722
|
-
In that case you cannot change the sources with a `||` operator
|
723
|
-
(since that doesn't short-circuit at `false`).
|
724
|
-
|
725
|
-
@function up.util.option
|
726
|
-
@param {Array} args...
|
727
|
-
@internal
|
728
|
-
###
|
729
|
-
option = (args...) ->
|
730
|
-
detect(args, isGiven)
|
731
|
-
|
732
|
-
###**
|
733
|
-
Passes each element in the given array to the given function.
|
777
|
+
Passes each element in the given [array-like value](/up.util.isList) to the given function.
|
734
778
|
Returns the first element for which the function returns a truthy value.
|
735
779
|
|
736
780
|
If no object matches, returns `undefined`.
|
737
781
|
|
738
|
-
@function up.util.
|
739
|
-
@param {
|
740
|
-
@param {Function(
|
782
|
+
@function up.util.find
|
783
|
+
@param {List<T>} list
|
784
|
+
@param {Function(value): boolean} tester
|
741
785
|
@return {T|undefined}
|
742
786
|
@stable
|
743
787
|
###
|
744
|
-
|
788
|
+
findInList = (list, tester) ->
|
745
789
|
match = undefined
|
746
|
-
for element in
|
790
|
+
for element in list
|
747
791
|
if tester(element)
|
748
792
|
match = element
|
749
793
|
break
|
@@ -751,41 +795,57 @@ up.util = (($) ->
|
|
751
795
|
|
752
796
|
###**
|
753
797
|
Returns whether the given function returns a truthy value
|
754
|
-
for any element in the given array.
|
798
|
+
for any element in the given [array-like value](/up.util.isList).
|
755
799
|
|
756
|
-
@function up.util.
|
757
|
-
@param {
|
758
|
-
@param {Function(
|
800
|
+
@function up.util.some
|
801
|
+
@param {List} list
|
802
|
+
@param {Function(value, index): boolean} tester
|
759
803
|
A function that will be called with each element and (optional) iteration index.
|
760
804
|
|
761
805
|
@return {boolean}
|
806
|
+
@stable
|
807
|
+
###
|
808
|
+
some = (list, tester) ->
|
809
|
+
!!findResult(list, tester)
|
810
|
+
|
811
|
+
###**
|
812
|
+
Consecutively calls the given function which each element
|
813
|
+
in the given array. Returns the first truthy return value.
|
814
|
+
|
815
|
+
Returned `undefined` iff the function does not return a truthy
|
816
|
+
value for any element in the array.
|
817
|
+
|
818
|
+
@function up.util.findResult
|
819
|
+
@param {Array} array
|
820
|
+
@param {Function(element): any} tester
|
821
|
+
A function that will be called with each element and (optional) iteration index.
|
822
|
+
|
823
|
+
@return {any|undefined}
|
762
824
|
@experimental
|
763
825
|
###
|
764
|
-
|
765
|
-
tester =
|
766
|
-
match = false
|
826
|
+
findResult = (array, tester) ->
|
827
|
+
tester = iteratee(tester)
|
767
828
|
for element, index in array
|
768
|
-
if tester(element, index)
|
769
|
-
|
770
|
-
|
771
|
-
match
|
829
|
+
if result = tester(element, index)
|
830
|
+
return result
|
831
|
+
return undefined
|
772
832
|
|
773
833
|
###**
|
774
834
|
Returns whether the given function returns a truthy value
|
775
|
-
for all elements in the given array.
|
835
|
+
for all elements in the given [array-like value](/up.util.isList).
|
776
836
|
|
777
|
-
@function up.util.
|
778
|
-
@param {
|
779
|
-
@param {Function(
|
837
|
+
@function up.util.every
|
838
|
+
@param {List} list
|
839
|
+
@param {Function(element, index): boolean} tester
|
780
840
|
A function that will be called with each element and (optional) iteration index.
|
781
841
|
|
782
842
|
@return {boolean}
|
783
843
|
@experimental
|
784
844
|
###
|
785
|
-
|
786
|
-
tester =
|
845
|
+
every = (list, tester) ->
|
846
|
+
tester = iteratee(tester)
|
787
847
|
match = true
|
788
|
-
for element, index in
|
848
|
+
for element, index in list
|
789
849
|
unless tester(element, index)
|
790
850
|
match = false
|
791
851
|
break
|
@@ -801,7 +861,7 @@ up.util = (($) ->
|
|
801
861
|
@stable
|
802
862
|
###
|
803
863
|
compact = (array) ->
|
804
|
-
|
864
|
+
filterList array, isGiven
|
805
865
|
|
806
866
|
###**
|
807
867
|
Returns the given array without duplicates.
|
@@ -821,16 +881,16 @@ up.util = (($) ->
|
|
821
881
|
for which uniquness is computed.
|
822
882
|
|
823
883
|
@function up.util.uniqBy
|
824
|
-
@param {Array
|
825
|
-
@param {Function
|
826
|
-
@return {Array
|
884
|
+
@param {Array} array
|
885
|
+
@param {Function(value): any} array
|
886
|
+
@return {Array}
|
827
887
|
@experimental
|
828
888
|
###
|
829
889
|
uniqBy = (array, mapper) ->
|
830
890
|
return array if array.length < 2
|
831
|
-
mapper =
|
891
|
+
mapper = iteratee(mapper)
|
832
892
|
set = new Set()
|
833
|
-
|
893
|
+
filterList array, (elem, index) ->
|
834
894
|
mapped = mapper(elem, index)
|
835
895
|
if set.has(mapped)
|
836
896
|
false
|
@@ -857,36 +917,36 @@ up.util = (($) ->
|
|
857
917
|
set
|
858
918
|
|
859
919
|
###**
|
860
|
-
Returns all elements from the given array that return
|
920
|
+
Returns all elements from the given [array-like value](/up.util.isList) that return
|
861
921
|
a truthy value when passed to the given function.
|
862
922
|
|
863
|
-
@function up.util.
|
864
|
-
@param {
|
865
|
-
@param {Function(
|
866
|
-
@return {Array
|
923
|
+
@function up.util.filter
|
924
|
+
@param {List} list
|
925
|
+
@param {Function(value, index): boolean} tester
|
926
|
+
@return {Array}
|
867
927
|
@stable
|
868
928
|
###
|
869
|
-
|
870
|
-
tester =
|
929
|
+
filterList = (list, tester) ->
|
930
|
+
tester = iteratee(tester)
|
871
931
|
matches = []
|
872
|
-
each
|
932
|
+
each list, (element, index) ->
|
873
933
|
if tester(element, index)
|
874
934
|
matches.push(element)
|
875
935
|
matches
|
876
936
|
|
877
937
|
###**
|
878
|
-
Returns all elements from the given array that do not return
|
938
|
+
Returns all elements from the given [array-like value](/up.util.isList) that do not return
|
879
939
|
a truthy value when passed to the given function.
|
880
940
|
|
881
941
|
@function up.util.reject
|
882
|
-
@param {
|
883
|
-
@param {Function(
|
884
|
-
@return {Array
|
942
|
+
@param {List} list
|
943
|
+
@param {Function(element, index): boolean} tester
|
944
|
+
@return {Array}
|
885
945
|
@stable
|
886
946
|
###
|
887
|
-
reject = (
|
888
|
-
tester =
|
889
|
-
|
947
|
+
reject = (list, tester) ->
|
948
|
+
tester = iteratee(tester)
|
949
|
+
filterList(list, (element, index) -> !tester(element, index))
|
890
950
|
|
891
951
|
###**
|
892
952
|
Returns the intersection of the given two arrays.
|
@@ -897,74 +957,45 @@ up.util = (($) ->
|
|
897
957
|
@internal
|
898
958
|
###
|
899
959
|
intersect = (array1, array2) ->
|
900
|
-
|
960
|
+
filterList array1, (element) ->
|
901
961
|
contains(array2, element)
|
902
962
|
|
903
|
-
addClass = (element, klassOrKlasses) ->
|
904
|
-
changeClassList(element, klassOrKlasses, 'add')
|
905
|
-
|
906
|
-
removeClass = (element, klassOrKlasses) ->
|
907
|
-
changeClassList(element, klassOrKlasses, 'remove')
|
908
|
-
|
909
|
-
changeClassList = (element, klassOrKlasses, fnName) ->
|
910
|
-
classList = getElement(element).classList
|
911
|
-
if isArray(klassOrKlasses)
|
912
|
-
each klassOrKlasses, (klass) ->
|
913
|
-
classList[fnName](klass)
|
914
|
-
else
|
915
|
-
classList[fnName](klassOrKlasses)
|
916
|
-
|
917
|
-
addTemporaryClass = (element, klassOrKlasses) ->
|
918
|
-
addClass(element, klassOrKlasses)
|
919
|
-
-> removeClass(element, klassOrKlasses)
|
920
|
-
|
921
|
-
hasClass = (element, klass) ->
|
922
|
-
classList = getElement(element).classList
|
923
|
-
classList.contains(klass)
|
924
|
-
|
925
|
-
###**
|
926
|
-
Returns the first [present](/up.util.isPresent) element attribute
|
927
|
-
among the given list of attribute names.
|
928
|
-
|
929
|
-
@function up.util.presentAttr
|
930
|
-
@internal
|
931
|
-
###
|
932
|
-
presentAttr = ($element, attrNames...) ->
|
933
|
-
values = ($element.attr(attrName) for attrName in attrNames)
|
934
|
-
detect(values, isPresent)
|
935
|
-
|
936
963
|
###**
|
937
964
|
Waits for the given number of milliseconds, the runs the given callback.
|
938
965
|
|
939
|
-
Instead of `up.util.
|
966
|
+
Instead of `up.util.timer(0, fn)` you can also use [`up.util.task(fn)`](/up.util.task).
|
940
967
|
|
941
|
-
@function up.util.
|
968
|
+
@function up.util.timer
|
942
969
|
@param {number} millis
|
943
|
-
@param {Function} callback
|
970
|
+
@param {Function()} callback
|
944
971
|
@stable
|
945
972
|
###
|
946
|
-
|
973
|
+
scheduleTimer = (millis, callback) ->
|
947
974
|
setTimeout(callback, millis)
|
948
975
|
|
949
976
|
###**
|
950
|
-
|
951
|
-
|
977
|
+
Pushes the given function to the [JavaScript task queue](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) (also "macrotask queue").
|
978
|
+
|
979
|
+
Equivalent to calling `setTimeout(fn, 0)`.
|
952
980
|
|
953
|
-
|
954
|
-
|
981
|
+
Also see `up.util.microtask()`.
|
982
|
+
|
983
|
+
@function up.util.task
|
984
|
+
@param {Function()} block
|
955
985
|
@stable
|
956
986
|
###
|
957
|
-
|
987
|
+
queueTask = (block) ->
|
958
988
|
setTimeout(block, 0)
|
959
989
|
|
960
990
|
###**
|
961
|
-
|
991
|
+
Pushes the given function to the [JavaScript microtask queue](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
|
962
992
|
|
963
|
-
@function up.util.
|
964
|
-
@param {Function} task
|
965
|
-
@
|
993
|
+
@function up.util.microtask
|
994
|
+
@param {Function()} task
|
995
|
+
@return {Promise}
|
996
|
+
@experimental
|
966
997
|
###
|
967
|
-
|
998
|
+
queueMicrotask = (task) ->
|
968
999
|
Promise.resolve().then(task)
|
969
1000
|
|
970
1001
|
###**
|
@@ -977,202 +1008,6 @@ up.util = (($) ->
|
|
977
1008
|
last = (array) ->
|
978
1009
|
array[array.length - 1]
|
979
1010
|
|
980
|
-
###**
|
981
|
-
Measures the drawable area of the document.
|
982
|
-
|
983
|
-
@function up.util.clientSize
|
984
|
-
@internal
|
985
|
-
###
|
986
|
-
clientSize = ->
|
987
|
-
element = document.documentElement
|
988
|
-
width: element.clientWidth
|
989
|
-
height: element.clientHeight
|
990
|
-
|
991
|
-
###**
|
992
|
-
Returns the width of a scrollbar.
|
993
|
-
|
994
|
-
This only runs once per page load.
|
995
|
-
|
996
|
-
@function up.util.scrollbarWidth
|
997
|
-
@internal
|
998
|
-
###
|
999
|
-
scrollbarWidth = memoize ->
|
1000
|
-
# This is how Bootstrap does it also:
|
1001
|
-
# https://github.com/twbs/bootstrap/blob/c591227602996c542b9fd0cb65cff3cc9519bdd5/dist/js/bootstrap.js#L1187
|
1002
|
-
$outer = $('<div>')
|
1003
|
-
outer = $outer.get(0)
|
1004
|
-
$outer.attr('up-viewport', '')
|
1005
|
-
writeInlineStyle outer,
|
1006
|
-
position: 'absolute'
|
1007
|
-
top: '0'
|
1008
|
-
left: '0'
|
1009
|
-
width: '100px'
|
1010
|
-
height: '100px' # Firefox needs at least 100px to show a scrollbar
|
1011
|
-
overflowY: 'scroll'
|
1012
|
-
$outer.appendTo(document.body)
|
1013
|
-
width = outer.offsetWidth - outer.clientWidth
|
1014
|
-
$outer.remove()
|
1015
|
-
width
|
1016
|
-
|
1017
|
-
###**
|
1018
|
-
Returns whether the given element is currently showing a vertical scrollbar.
|
1019
|
-
|
1020
|
-
@function up.util.documentHasVerticalScrollbar
|
1021
|
-
@internal
|
1022
|
-
###
|
1023
|
-
documentHasVerticalScrollbar = ->
|
1024
|
-
body = document.body
|
1025
|
-
$body = $(body)
|
1026
|
-
html = document.documentElement
|
1027
|
-
|
1028
|
-
bodyOverflow = readComputedStyle($body, 'overflowY')
|
1029
|
-
|
1030
|
-
forcedScroll = (bodyOverflow == 'scroll')
|
1031
|
-
forcedHidden = (bodyOverflow == 'hidden')
|
1032
|
-
|
1033
|
-
forcedScroll || (!forcedHidden && html.scrollHeight > html.clientHeight)
|
1034
|
-
|
1035
|
-
###**
|
1036
|
-
Temporarily sets the CSS for the given element.
|
1037
|
-
|
1038
|
-
@function up.util.writeTemporaryStyle
|
1039
|
-
@param {jQuery} $element
|
1040
|
-
@param {Object} css
|
1041
|
-
@param {Function} [block]
|
1042
|
-
If given, the CSS is set, the block is called and
|
1043
|
-
the old CSS is restored.
|
1044
|
-
@return {Function}
|
1045
|
-
A function that restores the original CSS when called.
|
1046
|
-
@internal
|
1047
|
-
###
|
1048
|
-
writeTemporaryStyle = (elementOrSelector, newCss, block) ->
|
1049
|
-
$element = $(elementOrSelector)
|
1050
|
-
oldStyles = readInlineStyle($element, Object.keys(newCss))
|
1051
|
-
restoreOldStyles = -> writeInlineStyle($element, oldStyles)
|
1052
|
-
writeInlineStyle($element, newCss)
|
1053
|
-
if block
|
1054
|
-
# If a block was passed, we run the block and restore old styles.
|
1055
|
-
block()
|
1056
|
-
restoreOldStyles()
|
1057
|
-
else
|
1058
|
-
# If no block was passed, we return the restoration function.
|
1059
|
-
restoreOldStyles
|
1060
|
-
|
1061
|
-
###**
|
1062
|
-
Forces a repaint of the given element.
|
1063
|
-
|
1064
|
-
@function up.util.forceRepaint
|
1065
|
-
@internal
|
1066
|
-
###
|
1067
|
-
forceRepaint = (element) ->
|
1068
|
-
element = getElement(element)
|
1069
|
-
element.offsetHeight
|
1070
|
-
|
1071
|
-
###**
|
1072
|
-
@function up.util.finishTransition
|
1073
|
-
@internal
|
1074
|
-
###
|
1075
|
-
concludeCssTransition = (element) ->
|
1076
|
-
undo = writeTemporaryStyle(element, transition: 'none')
|
1077
|
-
# Browsers need to paint at least one frame without a transition to stop the
|
1078
|
-
# animation. In theory we could just wait until the next paint, but in case
|
1079
|
-
# someone will set another transition after us, let's force a repaint here.
|
1080
|
-
forceRepaint(element)
|
1081
|
-
return undo
|
1082
|
-
|
1083
|
-
###**
|
1084
|
-
@internal
|
1085
|
-
###
|
1086
|
-
margins = (selectorOrElement) ->
|
1087
|
-
element = getElement(selectorOrElement)
|
1088
|
-
top: readComputedStyleNumber(element, 'marginTop')
|
1089
|
-
right: readComputedStyleNumber(element, 'marginRight')
|
1090
|
-
bottom: readComputedStyleNumber(element, 'marginBottom')
|
1091
|
-
left: readComputedStyleNumber(element, 'marginLeft')
|
1092
|
-
|
1093
|
-
###**
|
1094
|
-
Measures the given element.
|
1095
|
-
|
1096
|
-
@function up.util.measure
|
1097
|
-
@internal
|
1098
|
-
###
|
1099
|
-
measure = ($element, opts) ->
|
1100
|
-
opts = newOptions(opts, relative: false, inner: false, includeMargin: false)
|
1101
|
-
|
1102
|
-
if opts.relative
|
1103
|
-
if opts.relative == true
|
1104
|
-
coordinates = $element.position()
|
1105
|
-
else
|
1106
|
-
# A relative context element is given
|
1107
|
-
$context = $(opts.relative)
|
1108
|
-
elementCoords = $element.offset()
|
1109
|
-
if $context.is(document)
|
1110
|
-
# The document is always at the origin
|
1111
|
-
coordinates = elementCoords
|
1112
|
-
else
|
1113
|
-
contextCoords = $context.offset()
|
1114
|
-
coordinates =
|
1115
|
-
left: elementCoords.left - contextCoords.left
|
1116
|
-
top: elementCoords.top - contextCoords.top
|
1117
|
-
else
|
1118
|
-
coordinates = $element.offset()
|
1119
|
-
|
1120
|
-
box =
|
1121
|
-
left: coordinates.left
|
1122
|
-
top: coordinates.top
|
1123
|
-
|
1124
|
-
if opts.inner
|
1125
|
-
box.width = $element.width()
|
1126
|
-
box.height = $element.height()
|
1127
|
-
else
|
1128
|
-
box.width = $element.outerWidth()
|
1129
|
-
box.height = $element.outerHeight()
|
1130
|
-
|
1131
|
-
if opts.includeMargin
|
1132
|
-
mgs = margins($element)
|
1133
|
-
box.left -= mgs.left
|
1134
|
-
box.top -= mgs.top
|
1135
|
-
box.height += mgs.top + mgs.bottom
|
1136
|
-
box.width += mgs.left + mgs.right
|
1137
|
-
|
1138
|
-
box
|
1139
|
-
|
1140
|
-
###**
|
1141
|
-
Copies all attributes from the source element to the target element.
|
1142
|
-
|
1143
|
-
@function up.util.copyAttributes
|
1144
|
-
@internal
|
1145
|
-
###
|
1146
|
-
copyAttributes = ($source, $target) ->
|
1147
|
-
for attr in $source.get(0).attributes
|
1148
|
-
if attr.specified
|
1149
|
-
$target.attr(attr.name, attr.value)
|
1150
|
-
|
1151
|
-
###**
|
1152
|
-
Looks for the given selector in the element and its descendants.
|
1153
|
-
|
1154
|
-
@function up.util.selectInSubtree
|
1155
|
-
@internal
|
1156
|
-
###
|
1157
|
-
selectInSubtree = ($element, selector) ->
|
1158
|
-
# This implementation is faster than $element.find(selector).addBack(Seelctor)
|
1159
|
-
$matches = $()
|
1160
|
-
if $element.is(selector)
|
1161
|
-
$matches = $matches.add($element)
|
1162
|
-
$matches = $matches.add($element.find(selector))
|
1163
|
-
$matches
|
1164
|
-
|
1165
|
-
###**
|
1166
|
-
Looks for the given selector in the element, its descendants and its ancestors.
|
1167
|
-
|
1168
|
-
@function up.util.selectInDynasty
|
1169
|
-
@internal
|
1170
|
-
###
|
1171
|
-
selectInDynasty = ($element, selector) ->
|
1172
|
-
$subtree = selectInSubtree($element, selector)
|
1173
|
-
$ancestors = $element.parents(selector)
|
1174
|
-
$subtree.add($ancestors)
|
1175
|
-
|
1176
1011
|
###**
|
1177
1012
|
Returns whether the given keyboard event involved the ESC key.
|
1178
1013
|
|
@@ -1180,7 +1015,8 @@ up.util = (($) ->
|
|
1180
1015
|
@internal
|
1181
1016
|
###
|
1182
1017
|
escapePressed = (event) ->
|
1183
|
-
event.
|
1018
|
+
key = event.key
|
1019
|
+
key == 'Escape' || key == 'Esc'
|
1184
1020
|
|
1185
1021
|
###**
|
1186
1022
|
Returns whether the given array or string contains the given element or substring.
|
@@ -1193,34 +1029,6 @@ up.util = (($) ->
|
|
1193
1029
|
contains = (arrayOrString, elementOrSubstring) ->
|
1194
1030
|
arrayOrString.indexOf(elementOrSubstring) >= 0
|
1195
1031
|
|
1196
|
-
###**
|
1197
|
-
@function up.util.castedAttr
|
1198
|
-
@internal
|
1199
|
-
###
|
1200
|
-
castedAttr = ($element, attribute) ->
|
1201
|
-
value = $element.attr(attribute)
|
1202
|
-
switch value
|
1203
|
-
when 'false' then false
|
1204
|
-
when 'true', '', attribute then true
|
1205
|
-
else value # other strings, undefined, null, ...
|
1206
|
-
|
1207
|
-
###**
|
1208
|
-
@function up.util.jsonAttr
|
1209
|
-
@internal
|
1210
|
-
###
|
1211
|
-
jsonAttr = (elementOrSelector, attribute) ->
|
1212
|
-
if element = getElement(elementOrSelector)
|
1213
|
-
# The document does not respond to #getAttribute()
|
1214
|
-
json = element.getAttribute?(attribute)
|
1215
|
-
if isString(json) && trim(json) != ''
|
1216
|
-
JSON.parse(json)
|
1217
|
-
|
1218
|
-
# castsToTrue = (object) ->
|
1219
|
-
# String(object) == "true"
|
1220
|
-
#
|
1221
|
-
# castsToFalse = (object) ->
|
1222
|
-
# String(object) == "false"
|
1223
|
-
|
1224
1032
|
###**
|
1225
1033
|
Returns a copy of the given object that only contains
|
1226
1034
|
the given properties.
|
@@ -1278,31 +1086,11 @@ up.util = (($) ->
|
|
1278
1086
|
Returns a promise that will never be resolved.
|
1279
1087
|
|
1280
1088
|
@function up.util.unresolvablePromise
|
1281
|
-
@
|
1089
|
+
@internal
|
1282
1090
|
###
|
1283
1091
|
unresolvablePromise = ->
|
1284
1092
|
new Promise(noop)
|
1285
1093
|
|
1286
|
-
###**
|
1287
|
-
Returns an empty jQuery collection.
|
1288
|
-
|
1289
|
-
@function up.util.nullJQuery
|
1290
|
-
@internal
|
1291
|
-
###
|
1292
|
-
nullJQuery = ->
|
1293
|
-
$()
|
1294
|
-
|
1295
|
-
###**
|
1296
|
-
On the given element, set attributes that are still missing.
|
1297
|
-
|
1298
|
-
@function up.util.setMissingAttrs
|
1299
|
-
@internal
|
1300
|
-
###
|
1301
|
-
setMissingAttrs = ($element, attrs) ->
|
1302
|
-
for key, value of attrs
|
1303
|
-
if isMissing($element.attr(key))
|
1304
|
-
$element.attr(key, value)
|
1305
|
-
|
1306
1094
|
###**
|
1307
1095
|
Removes the given element from the given array.
|
1308
1096
|
|
@@ -1332,102 +1120,6 @@ up.util = (($) ->
|
|
1332
1120
|
else
|
1333
1121
|
value
|
1334
1122
|
|
1335
|
-
###**
|
1336
|
-
@function up.util.config
|
1337
|
-
@param {Object|Function} blueprint
|
1338
|
-
Default configuration options.
|
1339
|
-
Will be restored by calling `reset` on the returned object.
|
1340
|
-
@return {Object}
|
1341
|
-
An object with a `reset` function.
|
1342
|
-
@internal
|
1343
|
-
###
|
1344
|
-
config = (blueprint) ->
|
1345
|
-
hash = openConfig(blueprint)
|
1346
|
-
Object.preventExtensions(hash)
|
1347
|
-
hash
|
1348
|
-
|
1349
|
-
###**
|
1350
|
-
@function up.util.openConfig
|
1351
|
-
@internal
|
1352
|
-
###
|
1353
|
-
openConfig = (blueprint = {}) ->
|
1354
|
-
hash = {}
|
1355
|
-
hash.reset = ->
|
1356
|
-
opts = blueprint
|
1357
|
-
opts = opts() if isFunction(opts)
|
1358
|
-
assign(hash, opts)
|
1359
|
-
hash.reset()
|
1360
|
-
hash
|
1361
|
-
|
1362
|
-
###**
|
1363
|
-
@function up.util.unwrapElement
|
1364
|
-
@internal
|
1365
|
-
###
|
1366
|
-
unwrapElement = (wrapper) ->
|
1367
|
-
wrapper = getElement(wrapper)
|
1368
|
-
parent = wrapper.parentNode;
|
1369
|
-
wrappedNodes = toArray(wrapper.childNodes)
|
1370
|
-
each wrappedNodes, (wrappedNode) ->
|
1371
|
-
parent.insertBefore(wrappedNode, wrapper)
|
1372
|
-
parent.removeChild(wrapper)
|
1373
|
-
|
1374
|
-
###**
|
1375
|
-
@function up.util.offsetParent
|
1376
|
-
@internal
|
1377
|
-
###
|
1378
|
-
offsetParent = ($element) ->
|
1379
|
-
$match = undefined
|
1380
|
-
while ($element = $element.parent()) && $element.length
|
1381
|
-
position = readComputedStyle($element, 'position')
|
1382
|
-
if position == 'absolute' || position == 'relative' || $element.is('body')
|
1383
|
-
$match = $element
|
1384
|
-
break
|
1385
|
-
$match
|
1386
|
-
|
1387
|
-
###**
|
1388
|
-
Returns if the given element has a `fixed` position.
|
1389
|
-
|
1390
|
-
@function up.util.isFixed
|
1391
|
-
@internal
|
1392
|
-
###
|
1393
|
-
isFixed = (element) ->
|
1394
|
-
$element = $(element)
|
1395
|
-
loop
|
1396
|
-
position = readComputedStyle($element, 'position')
|
1397
|
-
if position == 'fixed'
|
1398
|
-
return true
|
1399
|
-
else
|
1400
|
-
$element = $element.parent()
|
1401
|
-
if $element.length == 0 || $element.is(document)
|
1402
|
-
return false
|
1403
|
-
|
1404
|
-
###**
|
1405
|
-
@function up.util.fixedToAbsolute
|
1406
|
-
@internal
|
1407
|
-
###
|
1408
|
-
fixedToAbsolute = (element, $viewport) ->
|
1409
|
-
$element = $(element)
|
1410
|
-
$futureOffsetParent = offsetParent($element)
|
1411
|
-
# To get a fixed elements distance from the edge of the screen,
|
1412
|
-
# use position(), not offset(). offset() would include the current
|
1413
|
-
# scrollTop of the viewport.
|
1414
|
-
elementCoords = $element.position()
|
1415
|
-
futureParentCoords = $futureOffsetParent.offset()
|
1416
|
-
writeInlineStyle $element,
|
1417
|
-
position: 'absolute'
|
1418
|
-
left: elementCoords.left - futureParentCoords.left
|
1419
|
-
top: elementCoords.top - futureParentCoords.top + $viewport.scrollTop()
|
1420
|
-
right: ''
|
1421
|
-
bottom: ''
|
1422
|
-
|
1423
|
-
# argNames = (fun) ->
|
1424
|
-
# code = fun.toString()
|
1425
|
-
# pattern = new RegExp('\\(([^\\)]*)\\)')
|
1426
|
-
# if match = code.match(pattern)
|
1427
|
-
# match[1].split(/\s*,\s*/)
|
1428
|
-
# else
|
1429
|
-
# error('Could not parse argument names of %o', fun)
|
1430
|
-
|
1431
1123
|
###**
|
1432
1124
|
Throws a [JavaScript error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
1433
1125
|
with the given message.
|
@@ -1461,9 +1153,9 @@ up.util = (($) ->
|
|
1461
1153
|
|
1462
1154
|
up.log.error(messageArgs...)
|
1463
1155
|
|
1464
|
-
|
1156
|
+
up.event.onReady(-> up.toast.open(messageArgs, toastOptions))
|
1465
1157
|
|
1466
|
-
asString = up.
|
1158
|
+
asString = up.log.sprintf(messageArgs...)
|
1467
1159
|
throw new Error(asString)
|
1468
1160
|
|
1469
1161
|
ESCAPE_HTML_ENTITY_MAP =
|
@@ -1478,11 +1170,19 @@ up.util = (($) ->
|
|
1478
1170
|
@function up.util.escapeHtml
|
1479
1171
|
@param {string} string
|
1480
1172
|
The text that should be escaped
|
1481
|
-
@
|
1173
|
+
@stable
|
1482
1174
|
###
|
1483
1175
|
escapeHtml = (string) ->
|
1484
1176
|
string.replace /[&<>"]/g, (char) -> ESCAPE_HTML_ENTITY_MAP[char]
|
1485
1177
|
|
1178
|
+
###**
|
1179
|
+
@function up.util.escapeRegexp
|
1180
|
+
@internal
|
1181
|
+
###
|
1182
|
+
escapeRegexp = (string) ->
|
1183
|
+
# From https://github.com/benjamingr/RegExp.escape
|
1184
|
+
string.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&')
|
1185
|
+
|
1486
1186
|
pluckKey = (object, key) ->
|
1487
1187
|
value = object[key]
|
1488
1188
|
delete object[key]
|
@@ -1491,118 +1191,41 @@ up.util = (($) ->
|
|
1491
1191
|
renameKey = (object, oldKey, newKey) ->
|
1492
1192
|
object[newKey] = pluckKey(object, oldKey)
|
1493
1193
|
|
1494
|
-
|
1495
|
-
if isDefined(object[oldKey])
|
1496
|
-
up.warn('Deprecated: Object key { %s } has been renamed to { %s } (found in %o)', oldKey, newKey, object)
|
1497
|
-
renameKey(object, oldKey, newKey)
|
1498
|
-
|
1499
|
-
pluckData = (elementOrSelector, key) ->
|
1500
|
-
$element = $(elementOrSelector)
|
1501
|
-
value = $element.data(key)
|
1502
|
-
$element.removeData(key)
|
1503
|
-
value
|
1504
|
-
|
1505
|
-
extractOptions = (args) ->
|
1194
|
+
extractLastArg = (args, tester) ->
|
1506
1195
|
lastArg = last(args)
|
1507
|
-
if
|
1508
|
-
args.pop()
|
1509
|
-
else
|
1510
|
-
{}
|
1196
|
+
if tester(lastArg)
|
1197
|
+
return args.pop()
|
1511
1198
|
|
1512
|
-
|
1199
|
+
# extractFirstArg = (args, tester) ->
|
1200
|
+
# firstArg = args[0]
|
1201
|
+
# if tester(firstArg)
|
1202
|
+
# return args.shift()
|
1513
1203
|
|
1514
|
-
|
1515
|
-
|
1516
|
-
parts = map parts, fn
|
1517
|
-
parts.join(separator)
|
1204
|
+
extractCallback = (args) ->
|
1205
|
+
extractLastArg(args, isFunction)
|
1518
1206
|
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
camelCase = (string) ->
|
1539
|
-
convertCase string, '', (part, i) ->
|
1540
|
-
if i == 0
|
1541
|
-
part.toLowerCase()
|
1542
|
-
else
|
1543
|
-
part.charAt(0).toUpperCase() + part.substr(1).toLowerCase()
|
1544
|
-
|
1545
|
-
###**
|
1546
|
-
Returns a copy of the given object with all keys renamed
|
1547
|
-
in `kebab-case`.
|
1548
|
-
|
1549
|
-
Does not change the given object.
|
1550
|
-
|
1551
|
-
@function up.util.kebabCaseKeys
|
1552
|
-
@param {object} obj
|
1553
|
-
@return {object}
|
1554
|
-
@internal
|
1555
|
-
###
|
1556
|
-
kebabCaseKeys = (obj) ->
|
1557
|
-
copyWithRenamedKeys(obj, kebabCase)
|
1558
|
-
|
1559
|
-
###**
|
1560
|
-
Returns a copy of the given object with all keys renamed
|
1561
|
-
in `camelCase`.
|
1562
|
-
|
1563
|
-
Does not change the given object.
|
1564
|
-
|
1565
|
-
@function up.util.camelCaseKeys
|
1566
|
-
@param {object} obj
|
1567
|
-
@return {object}
|
1568
|
-
@internal
|
1569
|
-
###
|
1570
|
-
camelCaseKeys = (obj) ->
|
1571
|
-
copyWithRenamedKeys(obj, camelCase)
|
1572
|
-
|
1573
|
-
# lowerCaseKeys = (obj) ->
|
1574
|
-
# copyWithRenamedKeys(obj, (key) -> key.toLowerCase())
|
1575
|
-
|
1576
|
-
copyWithRenamedKeys = (obj, keyTransformer) ->
|
1577
|
-
result = {}
|
1578
|
-
for k, v of obj
|
1579
|
-
k = keyTransformer(k)
|
1580
|
-
result[k] = v
|
1581
|
-
result
|
1582
|
-
|
1583
|
-
opacity = (element) ->
|
1584
|
-
readComputedStyleNumber(element, 'opacity')
|
1585
|
-
|
1586
|
-
whenReady = memoize ->
|
1587
|
-
if $.isReady
|
1588
|
-
Promise.resolve()
|
1589
|
-
else
|
1590
|
-
new Promise (resolve) -> $(resolve)
|
1207
|
+
extractOptions = (args) ->
|
1208
|
+
extractLastArg(args, isOptions) || {}
|
1209
|
+
|
1210
|
+
partial = (fn, fixedArgs...) ->
|
1211
|
+
return (callArgs...) ->
|
1212
|
+
fn.apply(this, fixedArgs.concat(callArgs))
|
1213
|
+
|
1214
|
+
#function throttle(callback, limit) { // From https://jsfiddle.net/jonathansampson/m7G64/
|
1215
|
+
# var wait = false // Initially, we're not waiting
|
1216
|
+
# return function () { // We return a throttled function
|
1217
|
+
# if (!wait) { // If we're not waiting
|
1218
|
+
# callback.call() // Execute users function
|
1219
|
+
# wait = true // Prevent future invocations
|
1220
|
+
# setTimeout(function () { // After a period of time
|
1221
|
+
# wait = false // And allow future invocations
|
1222
|
+
# }, limit)
|
1223
|
+
# }
|
1224
|
+
# }
|
1225
|
+
#}
|
1591
1226
|
|
1592
1227
|
identity = (arg) -> arg
|
1593
1228
|
|
1594
|
-
###**
|
1595
|
-
Returns whether the given element has been detached from the DOM
|
1596
|
-
(or whether it was never attached).
|
1597
|
-
|
1598
|
-
@function up.util.isDetached
|
1599
|
-
@internal
|
1600
|
-
###
|
1601
|
-
isDetached = (element) ->
|
1602
|
-
element = getElement(element)
|
1603
|
-
# This is by far the fastest way to do this
|
1604
|
-
not $.contains(document.documentElement, element)
|
1605
|
-
|
1606
1229
|
# ###**
|
1607
1230
|
# ###
|
1608
1231
|
# parsePath = (input) ->
|
@@ -1637,66 +1260,19 @@ up.util = (($) ->
|
|
1637
1260
|
preview.promise = deferred.promise()
|
1638
1261
|
preview
|
1639
1262
|
|
1640
|
-
###**
|
1641
|
-
A linear task queue whose (2..n)th tasks can be changed at any time.
|
1642
|
-
|
1643
|
-
@function up.util.DivertibleChain
|
1644
|
-
@internal
|
1645
|
-
###
|
1646
|
-
class DivertibleChain
|
1647
|
-
|
1648
|
-
constructor: ->
|
1649
|
-
@reset()
|
1650
|
-
|
1651
|
-
reset: =>
|
1652
|
-
@queue = []
|
1653
|
-
@currentTask = undefined
|
1654
|
-
|
1655
|
-
promise: =>
|
1656
|
-
lastTask = last(@allTasks())
|
1657
|
-
lastTask?.promise || Promise.resolve()
|
1658
|
-
|
1659
|
-
allTasks: =>
|
1660
|
-
tasks = []
|
1661
|
-
tasks.push(@currentTask) if @currentTask
|
1662
|
-
tasks = tasks.concat(@queue)
|
1663
|
-
tasks
|
1664
|
-
|
1665
|
-
poke: =>
|
1666
|
-
unless @currentTask # don't start a new task while we're still running one
|
1667
|
-
if @currentTask = @queue.shift()
|
1668
|
-
promise = @currentTask()
|
1669
|
-
always promise, =>
|
1670
|
-
@currentTask = undefined
|
1671
|
-
@poke()
|
1672
|
-
|
1673
|
-
asap: (newTasks...) =>
|
1674
|
-
@queue = map(newTasks, previewable)
|
1675
|
-
@poke()
|
1676
|
-
@promise()
|
1677
|
-
|
1678
|
-
###**
|
1679
|
-
@function up.util.submittedValue
|
1680
|
-
@internal
|
1681
|
-
###
|
1682
|
-
submittedValue = (fieldOrSelector) ->
|
1683
|
-
$field = $(fieldOrSelector)
|
1684
|
-
if $field.is('[type=checkbox], [type=radio]') && !$field.is(':checked')
|
1685
|
-
undefined
|
1686
|
-
else
|
1687
|
-
$field.val()
|
1688
|
-
|
1689
1263
|
###**
|
1690
1264
|
@function up.util.sequence
|
1691
|
-
@param {Array<Function>} functions
|
1692
|
-
@return {Function}
|
1265
|
+
@param {Array<Function()>} functions
|
1266
|
+
@return {Function()}
|
1693
1267
|
A function that will call all `functions` if called.
|
1694
1268
|
|
1695
1269
|
@internal
|
1696
1270
|
###
|
1697
|
-
sequence = (functions
|
1698
|
-
|
1699
|
-
|
1271
|
+
sequence = (functions) ->
|
1272
|
+
if functions.length == 1
|
1273
|
+
return functions[0]
|
1274
|
+
else
|
1275
|
+
return -> map(functions, (f) -> f())
|
1700
1276
|
|
1701
1277
|
# ###**
|
1702
1278
|
# @function up.util.race
|
@@ -1708,17 +1284,6 @@ up.util = (($) ->
|
|
1708
1284
|
# promise.then -> raceDone.resolve()
|
1709
1285
|
# raceDone.promise()
|
1710
1286
|
|
1711
|
-
###**
|
1712
|
-
@function up.util.promiseTimer
|
1713
|
-
@internal
|
1714
|
-
###
|
1715
|
-
promiseTimer = (ms) ->
|
1716
|
-
timeout = undefined
|
1717
|
-
promise = new Promise (resolve, reject) ->
|
1718
|
-
timeout = setTimer(ms, resolve)
|
1719
|
-
promise.cancel = -> clearTimeout(timeout)
|
1720
|
-
promise
|
1721
|
-
|
1722
1287
|
###**
|
1723
1288
|
Returns `'left'` if the center of the given element is in the left 50% of the screen.
|
1724
1289
|
Otherwise returns `'right'`.
|
@@ -1726,160 +1291,15 @@ up.util = (($) ->
|
|
1726
1291
|
@function up.util.horizontalScreenHalf
|
1727
1292
|
@internal
|
1728
1293
|
###
|
1729
|
-
horizontalScreenHalf = (
|
1730
|
-
elementDims =
|
1731
|
-
screenDims = clientSize()
|
1294
|
+
horizontalScreenHalf = (element) ->
|
1295
|
+
elementDims = element.getBoundingClientRect()
|
1732
1296
|
elementMid = elementDims.left + 0.5 * elementDims.width
|
1733
|
-
screenMid = 0.5 *
|
1297
|
+
screenMid = 0.5 * up.viewport.rootWidth()
|
1734
1298
|
if elementMid < screenMid
|
1735
1299
|
'left'
|
1736
1300
|
else
|
1737
1301
|
'right'
|
1738
1302
|
|
1739
|
-
###**
|
1740
|
-
Like `$old.replaceWith($new)`, but keeps event handlers bound to `$old`.
|
1741
|
-
|
1742
|
-
Note that this is a memory leak unless you re-attach `$old` to the DOM aferwards.
|
1743
|
-
|
1744
|
-
@function up.util.detachWith
|
1745
|
-
@internal
|
1746
|
-
###
|
1747
|
-
detachWith = ($old, $new) ->
|
1748
|
-
$insertion = $('<div></div>')
|
1749
|
-
$insertion.insertAfter($old)
|
1750
|
-
$old.detach()
|
1751
|
-
$insertion.replaceWith($new)
|
1752
|
-
$old
|
1753
|
-
|
1754
|
-
###**
|
1755
|
-
Hides the given element faster than `jQuery.fn.hide()`.
|
1756
|
-
|
1757
|
-
@function up.util.hide
|
1758
|
-
@param {jQuery|Element} element
|
1759
|
-
###
|
1760
|
-
hide = (element) ->
|
1761
|
-
writeInlineStyle(element, display: 'none')
|
1762
|
-
|
1763
|
-
###**
|
1764
|
-
Gets the computed style(s) for the given element.
|
1765
|
-
|
1766
|
-
@function up.util.readComputedStyle
|
1767
|
-
@param {jQuery|Element} element
|
1768
|
-
@param {String|Array} propOrProps
|
1769
|
-
One or more CSS property names in camelCase.
|
1770
|
-
@return {string|object}
|
1771
|
-
@internal
|
1772
|
-
###
|
1773
|
-
readComputedStyle = (element, props) ->
|
1774
|
-
element = getElement(element)
|
1775
|
-
style = window.getComputedStyle(element)
|
1776
|
-
extractFromStyleObject(style, props)
|
1777
|
-
|
1778
|
-
###**
|
1779
|
-
Gets a computed style value for the given element.
|
1780
|
-
If a value is set, the value is parsed to a number before returning.
|
1781
|
-
|
1782
|
-
@function up.util.readComputedStyleNumber
|
1783
|
-
@param {jQuery|Element} element
|
1784
|
-
@param {String} prop
|
1785
|
-
A CSS property name in camelCase.
|
1786
|
-
@return {string|object}
|
1787
|
-
@internal
|
1788
|
-
###
|
1789
|
-
readComputedStyleNumber = (element, prop) ->
|
1790
|
-
rawValue = readComputedStyle(element, prop)
|
1791
|
-
if isGiven(rawValue)
|
1792
|
-
parseFloat(rawValue)
|
1793
|
-
else
|
1794
|
-
undefined
|
1795
|
-
|
1796
|
-
###**
|
1797
|
-
Gets the given inline style(s) from the given element's `[style]` attribute.
|
1798
|
-
|
1799
|
-
@function up.util.readInlineStyle
|
1800
|
-
@param {jQuery|Element} element
|
1801
|
-
@param {String|Array} propOrProps
|
1802
|
-
One or more CSS property names in camelCase.
|
1803
|
-
@return {string|object}
|
1804
|
-
@internal
|
1805
|
-
###
|
1806
|
-
readInlineStyle = (element, props) ->
|
1807
|
-
element = getElement(element)
|
1808
|
-
style = element.style
|
1809
|
-
extractFromStyleObject(style, props)
|
1810
|
-
|
1811
|
-
extractFromStyleObject = (style, keyOrKeys) ->
|
1812
|
-
if isString(keyOrKeys)
|
1813
|
-
style[keyOrKeys]
|
1814
|
-
else # array
|
1815
|
-
only(style, keyOrKeys...)
|
1816
|
-
|
1817
|
-
###**
|
1818
|
-
Merges the given inline style(s) into the given element's `[style]` attribute.
|
1819
|
-
|
1820
|
-
@function up.util.readInlineStyle
|
1821
|
-
@param {jQuery|Element} element
|
1822
|
-
@param {Object} props
|
1823
|
-
One or more CSS properties with camelCase keys.
|
1824
|
-
@return {string|object}
|
1825
|
-
@internal
|
1826
|
-
###
|
1827
|
-
writeInlineStyle = (element, props) ->
|
1828
|
-
element = getElement(element)
|
1829
|
-
style = element.style
|
1830
|
-
for key, value of props
|
1831
|
-
value = normalizeStyleValueForWrite(key, value)
|
1832
|
-
style[key] = value
|
1833
|
-
|
1834
|
-
normalizeStyleValueForWrite = (key, value) ->
|
1835
|
-
if isMissing(value)
|
1836
|
-
value = ''
|
1837
|
-
else if CSS_LENGTH_PROPS.has(key)
|
1838
|
-
value = cssLength(value)
|
1839
|
-
value
|
1840
|
-
|
1841
|
-
CSS_LENGTH_PROPS = arrayToSet [
|
1842
|
-
'top', 'right', 'bottom', 'left',
|
1843
|
-
'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
|
1844
|
-
'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',
|
1845
|
-
'width', 'height',
|
1846
|
-
'maxWidth', 'maxHeight',
|
1847
|
-
'minWidth', 'minHeight',
|
1848
|
-
]
|
1849
|
-
|
1850
|
-
###**
|
1851
|
-
Converts the given value to a CSS length value, adding a `px` unit if required.
|
1852
|
-
|
1853
|
-
@function up.util.cssLength
|
1854
|
-
@internal
|
1855
|
-
###
|
1856
|
-
cssLength = (obj) ->
|
1857
|
-
if isNumber(obj) || (isString(obj) && /^\d+$/.test(obj))
|
1858
|
-
obj.toString() + "px"
|
1859
|
-
else
|
1860
|
-
obj
|
1861
|
-
|
1862
|
-
###**
|
1863
|
-
Returns whether the given element has a CSS transition set.
|
1864
|
-
|
1865
|
-
@function up.util.hasCssTransition
|
1866
|
-
@return {boolean}
|
1867
|
-
@internal
|
1868
|
-
###
|
1869
|
-
hasCssTransition = (elementOrStyleHash) ->
|
1870
|
-
if isOptions(elementOrStyleHash)
|
1871
|
-
style = elementOrStyleHash
|
1872
|
-
else
|
1873
|
-
element = getElement(element)
|
1874
|
-
style = getComputedStyle(element)
|
1875
|
-
|
1876
|
-
prop = style.transitionProperty
|
1877
|
-
duration = style.transitionDuration
|
1878
|
-
# The default transition for elements is actually "all 0s ease 0s"
|
1879
|
-
# instead of "none", although that has the same effect as "none".
|
1880
|
-
noTransition = (prop == 'none' || (prop == 'all' && duration == 0))
|
1881
|
-
not noTransition
|
1882
|
-
|
1883
1303
|
###**
|
1884
1304
|
Flattens the given `array` a single level deep.
|
1885
1305
|
|
@@ -1888,17 +1308,27 @@ up.util = (($) ->
|
|
1888
1308
|
An array which might contain other arrays
|
1889
1309
|
@return {Array}
|
1890
1310
|
The flattened array
|
1891
|
-
@
|
1311
|
+
@experimental
|
1892
1312
|
###
|
1893
1313
|
flatten = (array) ->
|
1894
1314
|
flattened = []
|
1895
1315
|
for object in array
|
1896
|
-
if
|
1897
|
-
flattened
|
1316
|
+
if isList(object)
|
1317
|
+
flattened.push(object...)
|
1898
1318
|
else
|
1899
1319
|
flattened.push(object)
|
1900
1320
|
flattened
|
1901
1321
|
|
1322
|
+
###**
|
1323
|
+
Maps each element using a mapping function,
|
1324
|
+
then flattens the result into a new array.
|
1325
|
+
|
1326
|
+
@function up.util.flatMap
|
1327
|
+
@param {Array} array
|
1328
|
+
@param {Function(element)} mapping
|
1329
|
+
@return {Array}
|
1330
|
+
@experimental
|
1331
|
+
###
|
1902
1332
|
flatMap = (array, block) ->
|
1903
1333
|
flatten map(array, block)
|
1904
1334
|
|
@@ -1975,7 +1405,7 @@ up.util = (($) ->
|
|
1975
1405
|
Promise.reject(error)
|
1976
1406
|
|
1977
1407
|
sum = (list, block) ->
|
1978
|
-
block =
|
1408
|
+
block = iteratee(block)
|
1979
1409
|
totalValue = 0
|
1980
1410
|
for entry in list
|
1981
1411
|
entryValue = block(entry)
|
@@ -1983,34 +1413,126 @@ up.util = (($) ->
|
|
1983
1413
|
totalValue += entryValue
|
1984
1414
|
totalValue
|
1985
1415
|
|
1416
|
+
isBasicObjectProperty = (k) ->
|
1417
|
+
Object.prototype.hasOwnProperty(k)
|
1418
|
+
|
1986
1419
|
###**
|
1987
|
-
Returns whether the
|
1420
|
+
Returns whether the two arguments are equal by value.
|
1988
1421
|
|
1989
|
-
|
1990
|
-
@internal
|
1991
|
-
###
|
1992
|
-
isBodyDescendant = (element) ->
|
1993
|
-
$(element).parents('body').length > 0
|
1422
|
+
\#\#\# Comparison protocol
|
1994
1423
|
|
1995
|
-
|
1996
|
-
|
1424
|
+
- By default `up.util.isEqual()` can compare strings, numbers,
|
1425
|
+
[array-like values](/up.util.isList), plain objects and `Date` objects.
|
1426
|
+
- To make the copying protocol work with user-defined classes,
|
1427
|
+
see `up.util.isEqual.key`.
|
1428
|
+
- Objects without a defined comparison protocol are
|
1429
|
+
defined by reference (`===`).
|
1997
1430
|
|
1431
|
+
@function up.util.isEqual
|
1432
|
+
@param {any} a
|
1433
|
+
@param {any} b
|
1434
|
+
@return {boolean}
|
1435
|
+
Whether the arguments are equal by value.
|
1436
|
+
@experimental
|
1437
|
+
###
|
1998
1438
|
isEqual = (a, b) ->
|
1439
|
+
a = a.valueOf() if a?.valueOf # Date, String objects, Number objects
|
1440
|
+
b = b.valueOf() if b?.valueOf # Date, String objects, Number objects
|
1999
1441
|
if typeof(a) != typeof(b)
|
2000
1442
|
false
|
2001
|
-
else if
|
2002
|
-
|
2003
|
-
else if isObject(a)
|
2004
|
-
|
1443
|
+
else if isList(a) && isList(b)
|
1444
|
+
isEqualList(a, b)
|
1445
|
+
else if isObject(a) && a[isEqual.key]
|
1446
|
+
a[isEqual.key](b)
|
1447
|
+
else if isOptions(a) && isOptions(b)
|
1448
|
+
aKeys = Object.keys(a)
|
1449
|
+
bKeys = Object.keys(b)
|
1450
|
+
if isEqualList(aKeys, bKeys)
|
1451
|
+
every aKeys, (aKey) -> isEqual(a[aKey], b[aKey])
|
1452
|
+
else
|
1453
|
+
false
|
2005
1454
|
else
|
2006
1455
|
a == b
|
2007
1456
|
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
1457
|
+
###**
|
1458
|
+
This property contains the name of a method that user-defined classes
|
1459
|
+
may implement to hook into the `up.util.isEqual()` protocol.
|
1460
|
+
|
1461
|
+
\#\#\# Example
|
1462
|
+
|
1463
|
+
We have a user-defined `Account` class that we want to use with `up.util.isEqual()`:
|
1464
|
+
|
1465
|
+
```
|
1466
|
+
class Account {
|
1467
|
+
constructor(email) {
|
1468
|
+
this.email = email
|
1469
|
+
}
|
1470
|
+
|
1471
|
+
[up.util.isEqual.key](other) {
|
1472
|
+
return this.email === other.email;
|
1473
|
+
}
|
1474
|
+
}
|
1475
|
+
```
|
1476
|
+
|
1477
|
+
Note that the protocol method is not actually named `'up.util.isEqual.key'`.
|
1478
|
+
Instead it is named after the *value* of the `up.util.isEqual.key` property.
|
1479
|
+
To do so, the code sample above is using a
|
1480
|
+
[computed property name](https://medium.com/front-end-weekly/javascript-object-creation-356e504173a8)
|
1481
|
+
in square brackets.
|
1482
|
+
|
1483
|
+
We may now use `Account` instances with `up.util.isEqual()`:
|
1484
|
+
|
1485
|
+
```
|
1486
|
+
one = new User('foo@foo.com')
|
1487
|
+
two = new User('foo@foo.com')
|
1488
|
+
three = new User('bar@bar.com')
|
1489
|
+
|
1490
|
+
isEqual = up.util.isEqual(one, two)
|
1491
|
+
// isEqual is now true
|
1492
|
+
|
1493
|
+
isEqual = up.util.isEqual(one, three)
|
1494
|
+
// isEqual is now false
|
1495
|
+
```
|
1496
|
+
|
1497
|
+
@property up.util.isEqual.key
|
1498
|
+
@param {string} key
|
1499
|
+
@experimental
|
1500
|
+
###
|
1501
|
+
isEqual.key = 'up.util.isEqual'
|
1502
|
+
|
1503
|
+
isEqualList = (a, b) ->
|
1504
|
+
a.length == b.length && every(a, (elem, index) -> isEqual(elem, b[index]))
|
1505
|
+
|
1506
|
+
splitValues = (value, separator = ' ') ->
|
1507
|
+
values = value.split(separator)
|
1508
|
+
values = map values, (v) -> v.trim()
|
1509
|
+
values = filterList(values, isPresent)
|
2012
1510
|
values
|
2013
1511
|
|
1512
|
+
endsWith = (string, search) ->
|
1513
|
+
if search.length > string.length
|
1514
|
+
false
|
1515
|
+
else
|
1516
|
+
string.substring(string.length - search.length) == search
|
1517
|
+
|
1518
|
+
simpleEase = (x) ->
|
1519
|
+
# easing: http://fooplot.com/?lang=de#W3sidHlwZSI6MCwiZXEiOiJ4PDAuNT8yKngqeDp4Kig0LXgqMiktMSIsImNvbG9yIjoiIzEzRjIxNyJ9LHsidHlwZSI6MCwiZXEiOiJzaW4oKHheMC43LTAuNSkqcGkpKjAuNSswLjUiLCJjb2xvciI6IiMxQTUyRUQifSx7InR5cGUiOjEwMDAsIndpbmRvdyI6WyItMS40NyIsIjEuNzgiLCItMC41NSIsIjEuNDUiXX1d
|
1520
|
+
# easing nice: sin((x^0.7-0.5)*pi)*0.5+0.5
|
1521
|
+
# easing performant: x < 0.5 ? 2*x*x : x*(4 - x*2)-1
|
1522
|
+
# https://jsperf.com/easings/1
|
1523
|
+
# Math.sin((Math.pow(x, 0.7) - 0.5) * Math.PI) * 0.5 + 0.5
|
1524
|
+
if x < 0.5
|
1525
|
+
2*x*x
|
1526
|
+
else
|
1527
|
+
x*(4 - x*2)-1
|
1528
|
+
|
1529
|
+
wrapValue = (object, constructor) ->
|
1530
|
+
if object instanceof constructor
|
1531
|
+
# This object has gone through instantiation and normalization before.
|
1532
|
+
object
|
1533
|
+
else
|
1534
|
+
new constructor(object)
|
1535
|
+
|
2014
1536
|
# wrapArray = (objOrArray) ->
|
2015
1537
|
# if isUndefined(objOrArray)
|
2016
1538
|
# []
|
@@ -2019,40 +1541,49 @@ up.util = (($) ->
|
|
2019
1541
|
# else
|
2020
1542
|
# [objOrArray]
|
2021
1543
|
|
1544
|
+
nextUid = 0
|
1545
|
+
|
1546
|
+
uid = ->
|
1547
|
+
nextUid++
|
1548
|
+
|
2022
1549
|
<% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
|
2023
|
-
offsetParent: offsetParent
|
2024
|
-
fixedToAbsolute: fixedToAbsolute
|
2025
|
-
isFixed: isFixed
|
2026
|
-
presentAttr: presentAttr
|
2027
1550
|
parseUrl: parseUrl
|
2028
1551
|
normalizeUrl: normalizeUrl
|
2029
1552
|
normalizeMethod: normalizeMethod
|
2030
1553
|
methodAllowsPayload: methodAllowsPayload
|
2031
|
-
createElementFromHtml: createElementFromHtml
|
2032
|
-
$createElementFromSelector: $createElementFromSelector
|
2033
|
-
$createPlaceholder: $createPlaceholder
|
2034
|
-
selectorForElement: selectorForElement
|
2035
1554
|
# isGoodSelector: isGoodSelector
|
2036
|
-
attributeSelector: attributeSelector
|
2037
1555
|
assign: assign
|
2038
1556
|
assignPolyfill: assignPolyfill
|
2039
1557
|
copy: copy
|
2040
|
-
|
1558
|
+
deepCopy: deepCopy
|
2041
1559
|
merge: merge
|
2042
1560
|
# deepAssign: deepAssign
|
2043
1561
|
# deepMerge: deepMerge
|
2044
1562
|
options: newOptions
|
2045
|
-
option: option
|
2046
1563
|
fail: fail
|
2047
1564
|
each: each
|
2048
1565
|
eachIterator: eachIterator
|
2049
1566
|
map: map
|
2050
1567
|
flatMap: flatMap
|
1568
|
+
mapObject: mapObject
|
2051
1569
|
times: times
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
1570
|
+
findResult: findResult
|
1571
|
+
some: some
|
1572
|
+
any: ->
|
1573
|
+
up.legacy.warn('up.util.any() has been renamed to up.util.some()')
|
1574
|
+
some.apply(null, arguments)
|
1575
|
+
every: every
|
1576
|
+
all: ->
|
1577
|
+
up.legacy.warn('up.util.all() has been renamed to up.util.every()')
|
1578
|
+
every.apply(null, arguments)
|
1579
|
+
detect: ->
|
1580
|
+
up.legacy.warn('up.util.find() has been renamed to up.util.find()')
|
1581
|
+
findInList.apply(null, arguments)
|
1582
|
+
find: findInList
|
1583
|
+
select: ->
|
1584
|
+
up.legacy.warn('up.util.select() has been renamed to up.util.filter()')
|
1585
|
+
filterList.apply(null, arguments)
|
1586
|
+
filter: filterList
|
2056
1587
|
reject: reject
|
2057
1588
|
intersect: intersect
|
2058
1589
|
compact: compact
|
@@ -2078,93 +1609,67 @@ up.util = (($) ->
|
|
2078
1609
|
isOptions: isOptions
|
2079
1610
|
isArray: isArray
|
2080
1611
|
isFormData: isFormData
|
1612
|
+
isNodeList: isNodeList
|
1613
|
+
isArguments: isArguments
|
1614
|
+
isList: isList
|
2081
1615
|
isUnmodifiedKeyEvent: isUnmodifiedKeyEvent
|
2082
1616
|
isUnmodifiedMouseEvent: isUnmodifiedMouseEvent
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
measure: measure
|
2088
|
-
addClass: addClass
|
2089
|
-
removeClass: removeClass
|
2090
|
-
hasClass: hasClass
|
2091
|
-
addTemporaryClass: addTemporaryClass
|
2092
|
-
writeTemporaryStyle: writeTemporaryStyle
|
2093
|
-
forceRepaint: forceRepaint
|
2094
|
-
concludeCssTransition: concludeCssTransition
|
1617
|
+
timer: scheduleTimer
|
1618
|
+
setTimer: ->
|
1619
|
+
up.legacy.warn('up.util.setTimer() has been renamed to up.util.timer()')
|
1620
|
+
scheduleTimer.apply(null, arguments)
|
2095
1621
|
escapePressed: escapePressed
|
2096
|
-
copyAttributes: copyAttributes
|
2097
|
-
selectInSubtree: selectInSubtree
|
2098
|
-
selectInDynasty: selectInDynasty
|
2099
1622
|
contains: contains
|
2100
1623
|
toArray: toArray
|
2101
|
-
castedAttr: castedAttr
|
2102
|
-
jsonAttr: jsonAttr
|
2103
|
-
clientSize: clientSize
|
2104
1624
|
only: only
|
2105
1625
|
except: except
|
2106
1626
|
# pickBy: pickBy
|
2107
|
-
trim: trim
|
2108
1627
|
unresolvablePromise: unresolvablePromise
|
2109
|
-
setMissingAttrs: setMissingAttrs
|
2110
1628
|
remove: remove
|
2111
1629
|
memoize: memoize
|
2112
|
-
scrollbarWidth: scrollbarWidth
|
2113
|
-
documentHasVerticalScrollbar: documentHasVerticalScrollbar
|
2114
|
-
config: config
|
2115
|
-
openConfig: openConfig
|
2116
|
-
unwrapElement: unwrapElement
|
2117
|
-
camelCase: camelCase
|
2118
|
-
camelCaseKeys: camelCaseKeys
|
2119
|
-
# lowerCaseKeys: lowerCaseKeys
|
2120
|
-
kebabCase: kebabCase
|
2121
|
-
kebabCaseKeys: kebabCaseKeys
|
2122
1630
|
error: fail
|
2123
|
-
pluckData: pluckData
|
2124
1631
|
pluckKey: pluckKey
|
2125
1632
|
renameKey: renameKey
|
2126
|
-
deprecateRenamedKey: deprecateRenamedKey
|
2127
1633
|
extractOptions: extractOptions
|
2128
|
-
|
1634
|
+
extractCallback: extractCallback
|
2129
1635
|
noop: noop
|
2130
1636
|
asyncNoop: asyncNoop
|
2131
|
-
opacity: opacity
|
2132
|
-
whenReady: whenReady
|
2133
1637
|
identity: identity
|
2134
1638
|
escapeHtml: escapeHtml
|
2135
|
-
|
2136
|
-
submittedValue: submittedValue
|
1639
|
+
escapeRegexp: escapeRegexp
|
2137
1640
|
sequence: sequence
|
2138
|
-
promiseTimer: promiseTimer
|
2139
1641
|
previewable: previewable
|
2140
1642
|
# parsePath: parsePath
|
2141
1643
|
evalOption: evalOption
|
2142
1644
|
horizontalScreenHalf: horizontalScreenHalf
|
2143
|
-
detachWith: detachWith
|
2144
1645
|
flatten: flatten
|
2145
1646
|
isTruthy: isTruthy
|
2146
|
-
isSingletonElement: isSingletonElement
|
2147
1647
|
newDeferred: newDeferred
|
2148
1648
|
always: always
|
2149
1649
|
muteRejection: muteRejection
|
2150
1650
|
rejectOnError: rejectOnError
|
2151
|
-
isBodyDescendant: isBodyDescendant
|
2152
1651
|
isBasicObjectProperty: isBasicObjectProperty
|
2153
1652
|
isCrossDomain: isCrossDomain
|
2154
|
-
|
1653
|
+
selectorForElement: ->
|
1654
|
+
up.legacy.warn('up.util.selectorForElement() has been renamed to up.element.toSelector()')
|
1655
|
+
up.element.toSelector.apply(null, arguments)
|
1656
|
+
nextFrame: ->
|
1657
|
+
up.legacy.warn('up.util.nextFrame() has been renamed to up.util.task()')
|
1658
|
+
queueTask.apply(null, arguments)
|
1659
|
+
task: queueTask
|
1660
|
+
microtask: queueMicrotask
|
2155
1661
|
isEqual: isEqual
|
2156
|
-
hide: hide
|
2157
|
-
cssLength: cssLength
|
2158
|
-
readComputedStyle: readComputedStyle
|
2159
|
-
readComputedStyleNumber: readComputedStyleNumber
|
2160
|
-
readInlineStyle: readInlineStyle
|
2161
|
-
writeInlineStyle: writeInlineStyle
|
2162
|
-
hasCssTransition: hasCssTransition
|
2163
1662
|
splitValues : splitValues
|
1663
|
+
endsWith: endsWith
|
2164
1664
|
sum: sum
|
2165
1665
|
# wrapArray: wrapArray
|
1666
|
+
wrapList: wrapList
|
1667
|
+
wrapValue: wrapValue
|
1668
|
+
simpleEase: simpleEase
|
2166
1669
|
values: objectValues
|
2167
|
-
|
2168
|
-
|
1670
|
+
partial: partial
|
1671
|
+
arrayToSet: arrayToSet
|
1672
|
+
setToArray: setToArray
|
1673
|
+
uid: uid
|
2169
1674
|
|
2170
1675
|
up.fail = up.util.fail
|