unpoly-rails 0.55.1 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -2
- data/dist/unpoly-bootstrap3.js +6 -4
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.js +1323 -805
- data/dist/unpoly.min.js +4 -3
- data/lib/assets/javascripts/unpoly-bootstrap3/{navigation-ext.coffee → feedback-ext.coffee} +2 -0
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +7 -7
- data/lib/assets/javascripts/unpoly/bus.coffee.erb +5 -6
- data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +127 -0
- data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +62 -32
- data/lib/assets/javascripts/unpoly/classes/url_set.coffee +27 -0
- data/lib/assets/javascripts/unpoly/dom.coffee.erb +78 -99
- data/lib/assets/javascripts/unpoly/feedback.coffee +147 -96
- data/lib/assets/javascripts/unpoly/form.coffee.erb +26 -2
- data/lib/assets/javascripts/unpoly/history.coffee +2 -1
- data/lib/assets/javascripts/unpoly/layout.coffee.erb +68 -12
- data/lib/assets/javascripts/unpoly/link.coffee.erb +10 -4
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +11 -9
- data/lib/assets/javascripts/unpoly/{motion.coffee → motion.coffee.erb} +184 -322
- data/lib/assets/javascripts/unpoly/popup.coffee.erb +13 -12
- data/lib/assets/javascripts/unpoly/radio.coffee +1 -1
- data/lib/assets/javascripts/unpoly/syntax.coffee +8 -17
- data/lib/assets/javascripts/unpoly/tooltip.coffee +11 -11
- data/lib/assets/javascripts/unpoly/util.coffee +332 -145
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/stylesheets/integration_test.sass +1 -0
- data/spec_app/app/assets/stylesheets/jasmine_specs.sass +4 -0
- data/spec_app/app/views/motion_test/transitions.erb +13 -0
- data/spec_app/app/views/pages/start.erb +1 -0
- data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +11 -0
- data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +5 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +217 -102
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +162 -44
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +97 -10
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +3 -3
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +22 -20
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +344 -228
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +194 -0
- metadata +11 -4
@@ -124,34 +124,35 @@ up.popup = (($) ->
|
|
124
124
|
config.reset()
|
125
125
|
|
126
126
|
align = ->
|
127
|
-
|
127
|
+
style = {}
|
128
128
|
|
129
129
|
popupBox = u.measure(state.$popup)
|
130
130
|
|
131
131
|
if u.isFixed(state.$anchor)
|
132
132
|
linkBox = state.$anchor.get(0).getBoundingClientRect()
|
133
|
-
|
133
|
+
style.position = 'fixed'
|
134
134
|
else
|
135
135
|
linkBox = u.measure(state.$anchor)
|
136
136
|
|
137
137
|
switch state.position
|
138
138
|
when 'bottom-right' # anchored to bottom-right of link, opens towards bottom-left
|
139
|
-
|
140
|
-
|
139
|
+
style.top = linkBox.top + linkBox.height
|
140
|
+
style.left = linkBox.left + linkBox.width - popupBox.width
|
141
141
|
when 'bottom-left' # anchored to bottom-left of link, opens towards bottom-right
|
142
|
-
|
143
|
-
|
142
|
+
style.top = linkBox.top + linkBox.height
|
143
|
+
style.left = linkBox.left
|
144
144
|
when 'top-right' # anchored to top-right of link, opens to top-left
|
145
|
-
|
146
|
-
|
145
|
+
style.top = linkBox.top - popupBox.height
|
146
|
+
style.left = linkBox.left + linkBox.width - popupBox.width
|
147
147
|
when 'top-left' # anchored to top-left of link, opens to top-right
|
148
|
-
|
149
|
-
|
148
|
+
style.top = linkBox.top - popupBox.height
|
149
|
+
style.left = linkBox.left
|
150
150
|
else
|
151
151
|
up.fail("Unknown position option '%s'", state.position)
|
152
152
|
|
153
153
|
state.$popup.attr('up-position', state.position)
|
154
|
-
|
154
|
+
|
155
|
+
u.writeInlineStyle(state.$popup, style)
|
155
156
|
|
156
157
|
discardHistory = ->
|
157
158
|
state.coveredTitle = null
|
@@ -344,7 +345,7 @@ up.popup = (($) ->
|
|
344
345
|
attachNow($link, options)
|
345
346
|
|
346
347
|
toggleAsap = ($link, options) ->
|
347
|
-
if $link
|
348
|
+
if u.hasClass($link, 'up-current')
|
348
349
|
closeAsap()
|
349
350
|
else
|
350
351
|
attachAsap($link, options)
|
@@ -376,22 +376,14 @@ up.syntax = (($) ->
|
|
376
376
|
@internal
|
377
377
|
###
|
378
378
|
clean = ($fragment) ->
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
prepareClean = ($fragment) ->
|
388
|
-
$candidates = u.selectInSubtree($fragment, ".#{DESTRUCTIBLE_CLASS}")
|
389
|
-
destructors = u.map $candidates, (candidate) -> $(candidate).data(DESTRUCTORS_KEY)
|
390
|
-
# Although destructible elements should always have an destructor function, we might be
|
391
|
-
# destroying a clone of such an element. E.g. Unpoly creates a clone when keeping an
|
392
|
-
# [up-keep] element, and that clone still has the .up-destructible class.
|
393
|
-
destructors = u.compact destructors
|
394
|
-
u.sequence(destructors...)
|
379
|
+
$destructibles = u.selectInSubtree($fragment, ".#{DESTRUCTIBLE_CLASS}")
|
380
|
+
u.each $destructibles, (destructible) ->
|
381
|
+
# The destructor function may be undefined at this point.
|
382
|
+
# Although destructible elements should always have an destructor function, we might be
|
383
|
+
# destroying a clone of such an element. E.g. Unpoly creates a clone when keeping an
|
384
|
+
# [up-keep] element, and that clone still has the .up-destructible class.
|
385
|
+
if destructor = $(destructible).data(DESTRUCTORS_KEY)
|
386
|
+
destructor()
|
395
387
|
|
396
388
|
###**
|
397
389
|
Checks if the given element has an [`up-data`](/up-data) attribute.
|
@@ -487,7 +479,6 @@ up.syntax = (($) ->
|
|
487
479
|
macro: macro
|
488
480
|
compile: compile
|
489
481
|
clean: clean
|
490
|
-
prepareClean: prepareClean
|
491
482
|
data: data
|
492
483
|
|
493
484
|
)(jQuery)
|
@@ -79,33 +79,33 @@ up.tooltip = (($) ->
|
|
79
79
|
config.reset()
|
80
80
|
|
81
81
|
align = ->
|
82
|
-
|
82
|
+
style = {}
|
83
83
|
tooltipBox = u.measure(state.$tooltip)
|
84
84
|
|
85
85
|
if u.isFixed(state.$anchor)
|
86
86
|
linkBox = state.$anchor.get(0).getBoundingClientRect()
|
87
|
-
|
87
|
+
style.position = 'fixed'
|
88
88
|
else
|
89
89
|
linkBox = u.measure(state.$anchor)
|
90
90
|
|
91
91
|
switch state.position
|
92
92
|
when 'top'
|
93
|
-
|
94
|
-
|
93
|
+
style.top = linkBox.top - tooltipBox.height
|
94
|
+
style.left = linkBox.left + 0.5 * (linkBox.width - tooltipBox.width)
|
95
95
|
when 'left'
|
96
|
-
|
97
|
-
|
96
|
+
style.top = linkBox.top + 0.5 * (linkBox.height - tooltipBox.height)
|
97
|
+
style.left = linkBox.left - tooltipBox.width
|
98
98
|
when 'right'
|
99
|
-
|
100
|
-
|
99
|
+
style.top = linkBox.top + 0.5 * (linkBox.height - tooltipBox.height)
|
100
|
+
style.left = linkBox.left + linkBox.width
|
101
101
|
when 'bottom'
|
102
|
-
|
103
|
-
|
102
|
+
style.top = linkBox.top + linkBox.height
|
103
|
+
style.left = linkBox.left + 0.5 * (linkBox.width - tooltipBox.width)
|
104
104
|
else
|
105
105
|
up.fail("Unknown position option '%s'", state.position)
|
106
106
|
|
107
107
|
state.$tooltip.attr('up-position', state.position)
|
108
|
-
state.$tooltip
|
108
|
+
u.writeInlineStyle(state.$tooltip, style)
|
109
109
|
|
110
110
|
createElement = (options) ->
|
111
111
|
$element = u.$createElementFromSelector('.up-tooltip')
|
@@ -15,7 +15,15 @@ up.util = (($) ->
|
|
15
15
|
@function up.util.noop
|
16
16
|
@experimental
|
17
17
|
###
|
18
|
-
noop =
|
18
|
+
noop = (->)
|
19
|
+
|
20
|
+
###**
|
21
|
+
A function that returns a resolved promise.
|
22
|
+
|
23
|
+
@function up.util.asyncNoop
|
24
|
+
@internal
|
25
|
+
###
|
26
|
+
asyncNoop = -> Promise.resolve()
|
19
27
|
|
20
28
|
###**
|
21
29
|
Ensures that the given function can only be called a single time.
|
@@ -97,7 +105,8 @@ up.util = (($) ->
|
|
97
105
|
###
|
98
106
|
parseUrl = (urlOrAnchor) ->
|
99
107
|
# In case someone passed us a $link, unwrap it
|
100
|
-
|
108
|
+
if isJQuery(urlOrAnchor)
|
109
|
+
urlOrAnchor = getElement(urlOrAnchor)
|
101
110
|
|
102
111
|
# If we are handed a parsed URL, just return it
|
103
112
|
if urlOrAnchor.pathname
|
@@ -159,7 +168,8 @@ up.util = (($) ->
|
|
159
168
|
$root
|
160
169
|
|
161
170
|
###**
|
162
|
-
@function $
|
171
|
+
@function $createPlaceHolder
|
172
|
+
@internal
|
163
173
|
###
|
164
174
|
$createPlaceholder = (selector, container = document.body) ->
|
165
175
|
$placeholder = $createElementFromSelector(selector)
|
@@ -273,6 +283,7 @@ up.util = (($) ->
|
|
273
283
|
@stable
|
274
284
|
###
|
275
285
|
map = (array, block) ->
|
286
|
+
return [] if array.length == 0
|
276
287
|
block = listBlock(block)
|
277
288
|
for item, index in array
|
278
289
|
block(item, index)
|
@@ -346,7 +357,7 @@ up.util = (($) ->
|
|
346
357
|
@stable
|
347
358
|
###
|
348
359
|
isMissing = (object) ->
|
349
|
-
isUndefined(object) || isNull(object)
|
360
|
+
isUndefined(object) || isNull(object)
|
350
361
|
|
351
362
|
###**
|
352
363
|
Returns whether the given argument is neither `undefined` nor `null`.
|
@@ -385,9 +396,11 @@ up.util = (($) ->
|
|
385
396
|
@stable
|
386
397
|
###
|
387
398
|
isBlank = (object) ->
|
388
|
-
isMissing(object)
|
389
|
-
|
390
|
-
(object.length == 0
|
399
|
+
return true if isMissing(object)
|
400
|
+
return false if isFunction(object)
|
401
|
+
return true if isObject(object) && Object.keys(object).length == 0 # object
|
402
|
+
return true if object.length == 0 # string, array, jQuery
|
403
|
+
return false
|
391
404
|
|
392
405
|
###**
|
393
406
|
Returns the given argument if the argument is [present](/up.util.isPresent),
|
@@ -566,16 +579,20 @@ up.util = (($) ->
|
|
566
579
|
object
|
567
580
|
|
568
581
|
###**
|
569
|
-
If given a jQuery collection, returns the
|
582
|
+
If given a jQuery collection, returns the first native DOM element in the collection.
|
583
|
+
If given a string, returns the first element matching that string.
|
570
584
|
If given any other argument, returns the argument unchanged.
|
571
585
|
|
572
|
-
@function up.util.
|
573
|
-
@param object
|
586
|
+
@function up.util.element
|
587
|
+
@param {jQuery|Element|String} object
|
588
|
+
@return {Element}
|
574
589
|
@internal
|
575
590
|
###
|
576
|
-
|
591
|
+
getElement = (object) ->
|
577
592
|
if isJQuery(object)
|
578
593
|
object.get(0)
|
594
|
+
else if isString(object)
|
595
|
+
$(object).get(0)
|
579
596
|
else
|
580
597
|
object
|
581
598
|
|
@@ -607,10 +624,9 @@ up.util = (($) ->
|
|
607
624
|
if defaults
|
608
625
|
for key, defaultValue of defaults
|
609
626
|
value = merged[key]
|
610
|
-
if
|
611
|
-
|
612
|
-
|
613
|
-
merged[key] = options(value, defaultValue)
|
627
|
+
if isMissing(value)
|
628
|
+
value = defaultValue
|
629
|
+
merged[key] = value
|
614
630
|
merged
|
615
631
|
|
616
632
|
###**
|
@@ -711,9 +727,7 @@ up.util = (($) ->
|
|
711
727
|
###
|
712
728
|
uniq = (array) ->
|
713
729
|
return array if array.length < 2
|
714
|
-
|
715
|
-
each array, (element) -> set.add(element)
|
716
|
-
setToArray(set)
|
730
|
+
setToArray(arrayToSet(array))
|
717
731
|
|
718
732
|
###*
|
719
733
|
This function is like [`uniq`](/up.util.uniq), accept that
|
@@ -747,6 +761,15 @@ up.util = (($) ->
|
|
747
761
|
set.forEach (elem) -> array.push(elem)
|
748
762
|
array
|
749
763
|
|
764
|
+
###*
|
765
|
+
@function up.util.arrayToSet
|
766
|
+
@internal
|
767
|
+
###
|
768
|
+
arrayToSet = (array) ->
|
769
|
+
set = new Set()
|
770
|
+
array.forEach (elem) -> set.add(elem)
|
771
|
+
set
|
772
|
+
|
750
773
|
###**
|
751
774
|
Returns all elements from the given array that return
|
752
775
|
a truthy value when passed to the given function.
|
@@ -791,6 +814,28 @@ up.util = (($) ->
|
|
791
814
|
select array1, (element) ->
|
792
815
|
contains(array2, element)
|
793
816
|
|
817
|
+
addClass = (element, klassOrKlasses) ->
|
818
|
+
changeClassList(element, klassOrKlasses, 'add')
|
819
|
+
|
820
|
+
removeClass = (element, klassOrKlasses) ->
|
821
|
+
changeClassList(element, klassOrKlasses, 'remove')
|
822
|
+
|
823
|
+
changeClassList = (element, klassOrKlasses, fnName) ->
|
824
|
+
classList = getElement(element).classList
|
825
|
+
if isArray(klassOrKlasses)
|
826
|
+
each klassOrKlasses, (klass) ->
|
827
|
+
classList[fnName](klass)
|
828
|
+
else
|
829
|
+
classList[fnName](klassOrKlasses)
|
830
|
+
|
831
|
+
addTemporaryClass = (element, klassOrKlasses) ->
|
832
|
+
addClass(element, klassOrKlasses)
|
833
|
+
-> removeClass(element, klassOrKlasses)
|
834
|
+
|
835
|
+
hasClass = (element, klass) ->
|
836
|
+
classList = getElement(element).classList
|
837
|
+
classList.contains(klass)
|
838
|
+
|
794
839
|
###**
|
795
840
|
Returns the first [present](/up.util.isPresent) element attribute
|
796
841
|
among the given list of attribute names.
|
@@ -869,8 +914,9 @@ up.util = (($) ->
|
|
869
914
|
# This is how Bootstrap does it also:
|
870
915
|
# https://github.com/twbs/bootstrap/blob/c591227602996c542b9fd0cb65cff3cc9519bdd5/dist/js/bootstrap.js#L1187
|
871
916
|
$outer = $('<div>')
|
917
|
+
outer = $outer.get(0)
|
872
918
|
$outer.attr('up-viewport', '')
|
873
|
-
|
919
|
+
writeInlineStyle outer,
|
874
920
|
position: 'absolute'
|
875
921
|
top: '0'
|
876
922
|
left: '0'
|
@@ -878,7 +924,6 @@ up.util = (($) ->
|
|
878
924
|
height: '100px' # Firefox needs at least 100px to show a scrollbar
|
879
925
|
overflowY: 'scroll'
|
880
926
|
$outer.appendTo(document.body)
|
881
|
-
outer = $outer.get(0)
|
882
927
|
width = outer.offsetWidth - outer.clientWidth
|
883
928
|
$outer.remove()
|
884
929
|
width
|
@@ -894,32 +939,17 @@ up.util = (($) ->
|
|
894
939
|
$body = $(body)
|
895
940
|
html = document.documentElement
|
896
941
|
|
897
|
-
bodyOverflow = $body
|
942
|
+
bodyOverflow = readComputedStyle($body, 'overflowY')
|
898
943
|
|
899
944
|
forcedScroll = (bodyOverflow == 'scroll')
|
900
945
|
forcedHidden = (bodyOverflow == 'hidden')
|
901
946
|
|
902
947
|
forcedScroll || (!forcedHidden && html.scrollHeight > html.clientHeight)
|
903
948
|
|
904
|
-
###**
|
905
|
-
Modifies the given function so it only runs once.
|
906
|
-
Subsequent calls will return the previous return value.
|
907
|
-
|
908
|
-
@function up.util.once
|
909
|
-
@param {Function} fun
|
910
|
-
@experimental
|
911
|
-
###
|
912
|
-
once = (fun) ->
|
913
|
-
result = undefined
|
914
|
-
(args...) ->
|
915
|
-
result = fun(args...) if fun?
|
916
|
-
fun = undefined
|
917
|
-
result
|
918
|
-
|
919
949
|
###**
|
920
950
|
Temporarily sets the CSS for the given element.
|
921
951
|
|
922
|
-
@function up.util.
|
952
|
+
@function up.util.writeTemporaryStyle
|
923
953
|
@param {jQuery} $element
|
924
954
|
@param {Object} css
|
925
955
|
@param {Function} [block]
|
@@ -929,35 +959,18 @@ up.util = (($) ->
|
|
929
959
|
A function that restores the original CSS when called.
|
930
960
|
@internal
|
931
961
|
###
|
932
|
-
|
962
|
+
writeTemporaryStyle = (elementOrSelector, newCss, block) ->
|
933
963
|
$element = $(elementOrSelector)
|
934
|
-
|
935
|
-
$element
|
936
|
-
|
964
|
+
oldStyles = readInlineStyle($element, Object.keys(newCss))
|
965
|
+
restoreOldStyles = -> writeInlineStyle($element, oldStyles)
|
966
|
+
writeInlineStyle($element, newCss)
|
937
967
|
if block
|
968
|
+
# If a block was passed, we run the block and restore old styles.
|
938
969
|
block()
|
939
|
-
|
940
|
-
else
|
941
|
-
once(memo)
|
942
|
-
|
943
|
-
###**
|
944
|
-
Forces the given jQuery element into an accelerated compositing layer.
|
945
|
-
|
946
|
-
@function up.util.forceCompositing
|
947
|
-
@internal
|
948
|
-
###
|
949
|
-
forceCompositing = ($element) ->
|
950
|
-
oldTransforms = $element.css(['transform', '-webkit-transform'])
|
951
|
-
if isBlank(oldTransforms) || oldTransforms['transform'] == 'none'
|
952
|
-
memo = -> $element.css(oldTransforms)
|
953
|
-
$element.css
|
954
|
-
'transform': 'translateZ(0)'
|
955
|
-
'-webkit-transform': 'translateZ(0)' # Safari
|
970
|
+
restoreOldStyles()
|
956
971
|
else
|
957
|
-
#
|
958
|
-
|
959
|
-
memo = ->
|
960
|
-
memo
|
972
|
+
# If no block was passed, we return the restoration function.
|
973
|
+
restoreOldStyles
|
961
974
|
|
962
975
|
###**
|
963
976
|
Forces a repaint of the given element.
|
@@ -966,21 +979,30 @@ up.util = (($) ->
|
|
966
979
|
@internal
|
967
980
|
###
|
968
981
|
forceRepaint = (element) ->
|
969
|
-
element =
|
982
|
+
element = getElement(element)
|
970
983
|
element.offsetHeight
|
971
984
|
|
972
|
-
|
985
|
+
###*
|
986
|
+
@function up.util.finishTransition
|
987
|
+
@internal
|
988
|
+
###
|
989
|
+
concludeCssTransition = (element) ->
|
990
|
+
undo = writeTemporaryStyle(element, transition: 'none')
|
991
|
+
# Browsers need to paint at least one frame without a transition to stop the
|
992
|
+
# animation. In theory we could just wait until the next paint, but in case
|
993
|
+
# someone will set another transition after us, let's force a repaint here.
|
994
|
+
forceRepaint(element)
|
995
|
+
return undo
|
973
996
|
|
974
997
|
###**
|
975
998
|
@internal
|
976
999
|
###
|
977
1000
|
margins = (selectorOrElement) ->
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
left: parseFloat(withUnits['margin-left'])
|
1001
|
+
element = getElement(selectorOrElement)
|
1002
|
+
top: readComputedStyleNumber(element, 'marginTop')
|
1003
|
+
right: readComputedStyleNumber(element, 'marginRight')
|
1004
|
+
bottom: readComputedStyleNumber(element, 'marginBottom')
|
1005
|
+
left: readComputedStyleNumber(element, 'marginLeft')
|
984
1006
|
|
985
1007
|
###**
|
986
1008
|
Measures the given element.
|
@@ -1047,7 +1069,12 @@ up.util = (($) ->
|
|
1047
1069
|
@internal
|
1048
1070
|
###
|
1049
1071
|
selectInSubtree = ($element, selector) ->
|
1050
|
-
$element.find(selector).addBack(
|
1072
|
+
# This implementation is faster than $element.find(selector).addBack(Seelctor)
|
1073
|
+
$matches = $()
|
1074
|
+
if $element.is(selector)
|
1075
|
+
$matches = $matches.add($element)
|
1076
|
+
$matches = $matches.add($element.find(selector))
|
1077
|
+
$matches
|
1051
1078
|
|
1052
1079
|
###**
|
1053
1080
|
Looks for the given selector in the element, its descendants and its ancestors.
|
@@ -1109,7 +1136,7 @@ up.util = (($) ->
|
|
1109
1136
|
only = (object, properties...) ->
|
1110
1137
|
filtered = {}
|
1111
1138
|
for property in properties
|
1112
|
-
if object
|
1139
|
+
if property of object
|
1113
1140
|
filtered[property] = object[property]
|
1114
1141
|
filtered
|
1115
1142
|
|
@@ -1188,63 +1215,6 @@ up.util = (($) ->
|
|
1188
1215
|
array.splice(index, 1)
|
1189
1216
|
element
|
1190
1217
|
|
1191
|
-
###**
|
1192
|
-
@function up.util.multiSelector
|
1193
|
-
@internal
|
1194
|
-
###
|
1195
|
-
multiSelector = (parts) ->
|
1196
|
-
|
1197
|
-
obj = {}
|
1198
|
-
selectors = []
|
1199
|
-
elements = []
|
1200
|
-
|
1201
|
-
for part in parts
|
1202
|
-
if isString(part)
|
1203
|
-
selectors.push(part)
|
1204
|
-
else
|
1205
|
-
elements.push(part)
|
1206
|
-
|
1207
|
-
obj.parsed = elements
|
1208
|
-
|
1209
|
-
if selectors.length
|
1210
|
-
# Although other methods would work with an array of
|
1211
|
-
# selectors, we combine them to a single separator for
|
1212
|
-
# performance reasons.
|
1213
|
-
combinedSelector = selectors.join(', ')
|
1214
|
-
obj.parsed.push(combinedSelector)
|
1215
|
-
|
1216
|
-
obj.select = ->
|
1217
|
-
obj.find(undefined)
|
1218
|
-
|
1219
|
-
obj.find = ($root) ->
|
1220
|
-
$result = nullJQuery()
|
1221
|
-
for selector in obj.parsed
|
1222
|
-
$matches = if $root then $root.find(selector) else $(selector)
|
1223
|
-
$result = $result.add($matches)
|
1224
|
-
$result
|
1225
|
-
|
1226
|
-
obj.selectInSubtree = ($start) ->
|
1227
|
-
$matches = obj.find($start)
|
1228
|
-
$matches = $matches.add($start) if obj.doesMatch($start)
|
1229
|
-
$matches
|
1230
|
-
|
1231
|
-
obj.doesMatch = (element) ->
|
1232
|
-
$element = $(element)
|
1233
|
-
any obj.parsed, (selector) -> $element.is(selector)
|
1234
|
-
|
1235
|
-
obj.seekUp = (start) ->
|
1236
|
-
$start = $(start)
|
1237
|
-
$element = $start
|
1238
|
-
$result = undefined
|
1239
|
-
while $element.length
|
1240
|
-
if obj.doesMatch($element)
|
1241
|
-
$result = $element
|
1242
|
-
break
|
1243
|
-
$element = $element.parent()
|
1244
|
-
$result || nullJQuery()
|
1245
|
-
|
1246
|
-
obj
|
1247
|
-
|
1248
1218
|
###**
|
1249
1219
|
If the given `value` is a function, calls the function with the given `args`.
|
1250
1220
|
Otherwise it just returns `value`.
|
@@ -1290,7 +1260,7 @@ up.util = (($) ->
|
|
1290
1260
|
@internal
|
1291
1261
|
###
|
1292
1262
|
unwrapElement = (wrapper) ->
|
1293
|
-
wrapper =
|
1263
|
+
wrapper = getElement(wrapper)
|
1294
1264
|
parent = wrapper.parentNode;
|
1295
1265
|
wrappedNodes = toArray(wrapper.childNodes)
|
1296
1266
|
each wrappedNodes, (wrappedNode) ->
|
@@ -1304,7 +1274,7 @@ up.util = (($) ->
|
|
1304
1274
|
offsetParent = ($element) ->
|
1305
1275
|
$match = undefined
|
1306
1276
|
while ($element = $element.parent()) && $element.length
|
1307
|
-
position = $element
|
1277
|
+
position = readComputedStyle($element, 'position')
|
1308
1278
|
if position == 'absolute' || position == 'relative' || $element.is('body')
|
1309
1279
|
$match = $element
|
1310
1280
|
break
|
@@ -1319,7 +1289,7 @@ up.util = (($) ->
|
|
1319
1289
|
isFixed = (element) ->
|
1320
1290
|
$element = $(element)
|
1321
1291
|
loop
|
1322
|
-
position = $element
|
1292
|
+
position = readComputedStyle($element, 'position')
|
1323
1293
|
if position == 'fixed'
|
1324
1294
|
return true
|
1325
1295
|
else
|
@@ -1339,7 +1309,7 @@ up.util = (($) ->
|
|
1339
1309
|
# scrollTop of the viewport.
|
1340
1310
|
elementCoords = $element.position()
|
1341
1311
|
futureParentCoords = $futureOffsetParent.offset()
|
1342
|
-
$element
|
1312
|
+
writeInlineStyle $element,
|
1343
1313
|
position: 'absolute'
|
1344
1314
|
left: elementCoords.left - futureParentCoords.left
|
1345
1315
|
top: elementCoords.top - futureParentCoords.top + $viewport.scrollTop()
|
@@ -1560,12 +1530,76 @@ up.util = (($) ->
|
|
1560
1530
|
else
|
1561
1531
|
{}
|
1562
1532
|
|
1533
|
+
CASE_CONVERSION_GROUP = /[^\-\_]+?(?=[A-Z\-\_]|$)/g
|
1534
|
+
|
1535
|
+
convertCase = (string, separator, fn) ->
|
1536
|
+
parts = string.match(CASE_CONVERSION_GROUP)
|
1537
|
+
parts = map parts, fn
|
1538
|
+
parts.join(separator)
|
1539
|
+
|
1540
|
+
###**
|
1541
|
+
Returns a copy of the given string that is transformed to `kebab-case`.
|
1542
|
+
|
1543
|
+
@function up.util.kebabCase
|
1544
|
+
@param {string} string
|
1545
|
+
@return {string}
|
1546
|
+
@internal
|
1547
|
+
###
|
1548
|
+
kebabCase = (string) ->
|
1549
|
+
convertCase string, '-', (part) -> part.toLowerCase()
|
1550
|
+
|
1551
|
+
###**
|
1552
|
+
Returns a copy of the given string that is transformed to `camelCase`.
|
1553
|
+
|
1554
|
+
@function up.util.camelCase
|
1555
|
+
@param {string} string
|
1556
|
+
@return {string}
|
1557
|
+
@internal
|
1558
|
+
###
|
1559
|
+
camelCase = (string) ->
|
1560
|
+
convertCase string, '', (part, i) ->
|
1561
|
+
if i == 0
|
1562
|
+
part.toLowerCase()
|
1563
|
+
else
|
1564
|
+
part.charAt(0).toUpperCase() + part.substr(1).toLowerCase()
|
1565
|
+
|
1566
|
+
###**
|
1567
|
+
Returns a copy of the given object with all keys renamed
|
1568
|
+
in `kebab-case`.
|
1569
|
+
|
1570
|
+
Does not change the given object.
|
1571
|
+
|
1572
|
+
@function up.util.kebabCaseKeys
|
1573
|
+
@param {object} obj
|
1574
|
+
@return {object}
|
1575
|
+
@internal
|
1576
|
+
###
|
1577
|
+
kebabCaseKeys = (obj) ->
|
1578
|
+
copyWithRenamedKeys(obj, kebabCase)
|
1579
|
+
|
1580
|
+
###**
|
1581
|
+
Returns a copy of the given object with all keys renamed
|
1582
|
+
in `camelCase`.
|
1583
|
+
|
1584
|
+
Does not change the given object.
|
1585
|
+
|
1586
|
+
@function up.util.camelCaseKeys
|
1587
|
+
@param {object} obj
|
1588
|
+
@return {object}
|
1589
|
+
@internal
|
1590
|
+
###
|
1591
|
+
camelCaseKeys = (obj) ->
|
1592
|
+
copyWithRenamedKeys(obj, camelCase)
|
1593
|
+
|
1594
|
+
copyWithRenamedKeys = (obj, keyTransformer) ->
|
1595
|
+
result = {}
|
1596
|
+
for k, v of obj
|
1597
|
+
k = keyTransformer(k)
|
1598
|
+
result[k] = v
|
1599
|
+
result
|
1600
|
+
|
1563
1601
|
opacity = (element) ->
|
1564
|
-
|
1565
|
-
if isGiven(rawOpacity)
|
1566
|
-
parseFloat(rawOpacity)
|
1567
|
-
else
|
1568
|
-
undefined
|
1602
|
+
readComputedStyleNumber(element, 'opacity')
|
1569
1603
|
|
1570
1604
|
whenReady = memoize ->
|
1571
1605
|
if $.isReady
|
@@ -1583,7 +1617,7 @@ up.util = (($) ->
|
|
1583
1617
|
@internal
|
1584
1618
|
###
|
1585
1619
|
isDetached = (element) ->
|
1586
|
-
element =
|
1620
|
+
element = getElement(element)
|
1587
1621
|
# This is by far the fastest way to do this
|
1588
1622
|
not $.contains(document.documentElement, element)
|
1589
1623
|
|
@@ -1726,6 +1760,135 @@ up.util = (($) ->
|
|
1726
1760
|
$insertion.replaceWith($new)
|
1727
1761
|
$old
|
1728
1762
|
|
1763
|
+
###**
|
1764
|
+
Hides the given element faster than `jQuery.fn.hide()`.
|
1765
|
+
|
1766
|
+
@function up.util.hide
|
1767
|
+
@param {jQuery|Element} element
|
1768
|
+
###
|
1769
|
+
hide = (element) ->
|
1770
|
+
writeInlineStyle(element, display: 'none')
|
1771
|
+
|
1772
|
+
###**
|
1773
|
+
Gets the computed style(s) for the given element.
|
1774
|
+
|
1775
|
+
@function up.util.readComputedStyle
|
1776
|
+
@param {jQuery|Element} element
|
1777
|
+
@param {String|Array} propOrProps
|
1778
|
+
One or more CSS property names in camelCase.
|
1779
|
+
@return {string|object}
|
1780
|
+
@internal
|
1781
|
+
###
|
1782
|
+
readComputedStyle = (element, props) ->
|
1783
|
+
element = getElement(element)
|
1784
|
+
style = window.getComputedStyle(element)
|
1785
|
+
extractFromStyleObject(style, props)
|
1786
|
+
|
1787
|
+
###**
|
1788
|
+
Gets a computed style value for the given element.
|
1789
|
+
If a value is set, the value is parsed to a number before returning.
|
1790
|
+
|
1791
|
+
@function up.util.readComputedStyleNumber
|
1792
|
+
@param {jQuery|Element} element
|
1793
|
+
@param {String} prop
|
1794
|
+
A CSS property name in camelCase.
|
1795
|
+
@return {string|object}
|
1796
|
+
@internal
|
1797
|
+
###
|
1798
|
+
readComputedStyleNumber = (element, prop) ->
|
1799
|
+
rawValue = readComputedStyle(element, prop)
|
1800
|
+
if isGiven(rawValue)
|
1801
|
+
parseFloat(rawValue)
|
1802
|
+
else
|
1803
|
+
undefined
|
1804
|
+
|
1805
|
+
###**
|
1806
|
+
Gets the given inline style(s) from the given element's `[style]` attribute.
|
1807
|
+
|
1808
|
+
@function up.util.readInlineStyle
|
1809
|
+
@param {jQuery|Element} element
|
1810
|
+
@param {String|Array} propOrProps
|
1811
|
+
One or more CSS property names in camelCase.
|
1812
|
+
@return {string|object}
|
1813
|
+
@internal
|
1814
|
+
###
|
1815
|
+
readInlineStyle = (element, props) ->
|
1816
|
+
element = getElement(element)
|
1817
|
+
style = element.style
|
1818
|
+
extractFromStyleObject(style, props)
|
1819
|
+
|
1820
|
+
extractFromStyleObject = (style, keyOrKeys) ->
|
1821
|
+
if isString(keyOrKeys)
|
1822
|
+
style[keyOrKeys]
|
1823
|
+
else # array
|
1824
|
+
only(style, keyOrKeys...)
|
1825
|
+
|
1826
|
+
###**
|
1827
|
+
Merges the given inline style(s) into the given element's `[style]` attribute.
|
1828
|
+
|
1829
|
+
@function up.util.readInlineStyle
|
1830
|
+
@param {jQuery|Element} element
|
1831
|
+
@param {Object} props
|
1832
|
+
One or more CSS properties with camelCase keys.
|
1833
|
+
@return {string|object}
|
1834
|
+
@internal
|
1835
|
+
###
|
1836
|
+
writeInlineStyle = (element, props) ->
|
1837
|
+
element = getElement(element)
|
1838
|
+
style = element.style
|
1839
|
+
for key, value of props
|
1840
|
+
value = normalizeStyleValueForWrite(key, value)
|
1841
|
+
style[key] = value
|
1842
|
+
|
1843
|
+
normalizeStyleValueForWrite = (key, value) ->
|
1844
|
+
if isMissing(value)
|
1845
|
+
value = ''
|
1846
|
+
else if CSS_LENGTH_PROPS.has(key)
|
1847
|
+
value = cssLength(value)
|
1848
|
+
value
|
1849
|
+
|
1850
|
+
CSS_LENGTH_PROPS = arrayToSet [
|
1851
|
+
'top', 'right', 'bottom', 'left',
|
1852
|
+
'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
|
1853
|
+
'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',
|
1854
|
+
'width', 'height',
|
1855
|
+
'maxWidth', 'maxHeight',
|
1856
|
+
'minWidth', 'minHeight',
|
1857
|
+
]
|
1858
|
+
|
1859
|
+
###*
|
1860
|
+
Converts the given value to a CSS length value, adding a `px` unit if required.
|
1861
|
+
|
1862
|
+
@function up.util.cssLength
|
1863
|
+
@internal
|
1864
|
+
###
|
1865
|
+
cssLength = (obj) ->
|
1866
|
+
if isNumber(obj) || (isString(obj) && /^\d+$/.test(obj))
|
1867
|
+
obj.toString() + "px"
|
1868
|
+
else
|
1869
|
+
obj
|
1870
|
+
|
1871
|
+
###*
|
1872
|
+
Returns whether the given element has a CSS transition set.
|
1873
|
+
|
1874
|
+
@function up.util.hasCssTransition
|
1875
|
+
@return {boolean}
|
1876
|
+
@internal
|
1877
|
+
###
|
1878
|
+
hasCssTransition = (elementOrStyleHash) ->
|
1879
|
+
if isOptions(elementOrStyleHash)
|
1880
|
+
style = elementOrStyleHash
|
1881
|
+
else
|
1882
|
+
element = getElement(element)
|
1883
|
+
style = getComputedStyle(element)
|
1884
|
+
|
1885
|
+
prop = style.transitionProperty
|
1886
|
+
duration = style.transitionDuration
|
1887
|
+
# The default transition for elements is actually "all 0s ease 0s"
|
1888
|
+
# instead of "none", although that has the same effect as "none".
|
1889
|
+
noTransition = (prop == 'none' || (prop == 'all' && duration == 0))
|
1890
|
+
not noTransition
|
1891
|
+
|
1729
1892
|
###**
|
1730
1893
|
Flattens the given `array` a single level deep.
|
1731
1894
|
|
@@ -1822,6 +1985,16 @@ up.util = (($) ->
|
|
1822
1985
|
isBodyDescendant = (element) ->
|
1823
1986
|
$(element).parents('body').length > 0
|
1824
1987
|
|
1988
|
+
isEqual = (a, b) ->
|
1989
|
+
if typeof(a) != typeof(b)
|
1990
|
+
false
|
1991
|
+
else if isArray(a)
|
1992
|
+
a.length == b.length && all(a, (elem, index) -> isEqual(elem, b[index]))
|
1993
|
+
else if isObject(a)
|
1994
|
+
fail('isEqual cannot compare objects yet')
|
1995
|
+
else
|
1996
|
+
a == b
|
1997
|
+
|
1825
1998
|
requestDataAsArray: requestDataAsArray
|
1826
1999
|
requestDataAsQuery: requestDataAsQuery
|
1827
2000
|
appendRequestData: appendRequestData
|
@@ -1880,14 +2053,17 @@ up.util = (($) ->
|
|
1880
2053
|
isUnmodifiedKeyEvent: isUnmodifiedKeyEvent
|
1881
2054
|
isUnmodifiedMouseEvent: isUnmodifiedMouseEvent
|
1882
2055
|
nullJQuery: nullJQuery
|
1883
|
-
|
2056
|
+
element: getElement
|
1884
2057
|
setTimer: setTimer
|
1885
2058
|
nextFrame: nextFrame
|
1886
2059
|
measure: measure
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
2060
|
+
addClass: addClass
|
2061
|
+
removeClass: removeClass
|
2062
|
+
hasClass: hasClass
|
2063
|
+
addTemporaryClass: addTemporaryClass
|
2064
|
+
writeTemporaryStyle: writeTemporaryStyle
|
1890
2065
|
forceRepaint: forceRepaint
|
2066
|
+
concludeCssTransition: concludeCssTransition
|
1891
2067
|
escapePressed: escapePressed
|
1892
2068
|
copyAttributes: copyAttributes
|
1893
2069
|
selectInSubtree: selectInSubtree
|
@@ -1908,7 +2084,10 @@ up.util = (($) ->
|
|
1908
2084
|
config: config
|
1909
2085
|
openConfig: openConfig
|
1910
2086
|
unwrapElement: unwrapElement
|
1911
|
-
|
2087
|
+
camelCase: camelCase
|
2088
|
+
camelCaseKeys: camelCaseKeys
|
2089
|
+
kebabCase: kebabCase
|
2090
|
+
kebabCaseKeys: kebabCaseKeys
|
1912
2091
|
error: fail
|
1913
2092
|
pluckData: pluckData
|
1914
2093
|
pluckKey: pluckKey
|
@@ -1916,6 +2095,7 @@ up.util = (($) ->
|
|
1916
2095
|
extractOptions: extractOptions
|
1917
2096
|
isDetached: isDetached
|
1918
2097
|
noop: noop
|
2098
|
+
asyncNoop: asyncNoop
|
1919
2099
|
opacity: opacity
|
1920
2100
|
whenReady: whenReady
|
1921
2101
|
identity: identity
|
@@ -1937,7 +2117,14 @@ up.util = (($) ->
|
|
1937
2117
|
isBodyDescendant: isBodyDescendant
|
1938
2118
|
isCrossDomain: isCrossDomain
|
1939
2119
|
microtask: microtask
|
1940
|
-
|
2120
|
+
isEqual: isEqual
|
2121
|
+
hide: hide
|
2122
|
+
cssLength: cssLength
|
2123
|
+
readComputedStyle: readComputedStyle
|
2124
|
+
readComputedStyleNumber: readComputedStyleNumber
|
2125
|
+
readInlineStyle: readInlineStyle
|
2126
|
+
writeInlineStyle: writeInlineStyle
|
2127
|
+
hasCssTransition: hasCssTransition
|
1941
2128
|
|
1942
2129
|
)(jQuery)
|
1943
2130
|
|