` | `undefined` |
| `
` | `undefined` |
@function up.element.booleanAttr
@param {Element} element
The element from which to retrieve the attribute value.
@param {String} attribute
The attribute name.
@return {boolean|undefined}
The cast attribute value.
@experimental
###
booleanAttr = (element, attribute, pass) ->
value = element.getAttribute(attribute)
switch value
when 'false'
false
when 'true', '', attribute
true
else
value if pass
###**
Returns the given attribute value cast as boolean.
If the attribute value cannot be cast, returns the attribute value unchanged.
@internal
###
booleanOrStringAttr = (element, attribute) ->
booleanAttr(element, attribute, true)
###**
Returns the value of the given attribute on the given element, cast to a number.
If the attribute value cannot be cast to a number, `undefined` is returned.
@function up.element.numberAttr
@param {Element} element
The element from which to retrieve the attribute value.
@param {String} attribute
The attribute name.
@return {number|undefined}
The cast attribute value.
@experimental
###
numberAttr = (element, attribute) ->
value = element.getAttribute(attribute)
if value?.match(/^[\d\.]+$/)
parseFloat(value)
###**
Reads the given attribute from the element, parsed as [JSON](https://www.json.org/).
Returns `undefined` if the attribute value is [blank](/up.util.isBlank).
Throws a `SyntaxError` if the attribute value is an invalid JSON string.
@function up.element.jsonAttr
@param {Element} element
The element from which to retrieve the attribute value.
@param {String} attribute
The attribute name.
@return {Object|undefined}
The cast attribute value.
@experimental
###
jsonAttr = (element, attribute) ->
# The document does not respond to #getAttribute()
if json = element.getAttribute?(attribute)?.trim()
JSON.parse(json)
###**
Temporarily sets the inline CSS styles on the given element.
Returns a function that restores the original inline styles when called.
\#\#\# Example
element = document.querySelector('div')
unhide = up.element.setTemporaryStyle(element, { 'visibility': 'hidden' })
// do things while element is invisible
unhide()
// element is visible again
@function up.element.setTemporaryStyle
@param {Element} element
The element to style.
@param {Object} styles
An object of CSS property names and values.
@return {Function()}
A function that restores the original inline styles when called.
@internal
###
setTemporaryStyle = (element, newStyles, block) ->
oldStyles = inlineStyle(element, Object.keys(newStyles))
setInlineStyle(element, newStyles)
return -> setInlineStyle(element, oldStyles)
###**
Receives [computed CSS styles](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
for the given element.
\#\#\# Examples
When requesting a single CSS property, its value will be returned as a string:
value = up.element.style(element, 'font-size')
// value is '16px'
When requesting multiple CSS properties, the function returns an object of property names and values:
value = up.element.style(element, ['font-size', 'margin-top'])
// value is { 'font-size': '16px', 'margin-top': '10px' }
@function up.element.style
@param {Element} element
@param {String|Array} propOrProps
One or more CSS property names in kebab-case or camelCase.
@return {string|object}
@experimental
###
computedStyle = (element, props) ->
style = window.getComputedStyle(element)
extractFromStyleObject(style, props)
###**
Receives a [computed CSS property value](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
for the given element, casted as a number.
The value is casted by removing the property's [unit](https://www.w3schools.com/cssref/css_units.asp) (which is usually `px` for computed properties).
The result is then parsed as a floating point number.
Returns `undefined` if the property value is missing, or if it cannot
be parsed as a number.
\#\#\# Examples
When requesting a single CSS property, its value will be returned as a string:
value = up.element.style(element, 'font-size')
// value is '16px'
value = up.element.styleNumber(element, 'font-size')
// value is 16
@function up.element.styleNumber
@param {Element} element
@param {String} prop
A single property name in kebab-case or camelCase.
@return {number|undefined}
@experimental
###
computedStyleNumber = (element, prop) ->
rawValue = computedStyle(element, prop)
if u.isGiven(rawValue)
parseFloat(rawValue)
else
undefined
###**
Gets the given inline style(s) from the given element's `[style]` attribute.
@function up.element.inlineStyle
@param {Element} element
@param {String|Array} propOrProps
One or more CSS property names in kebab-case or camelCase.
@return {string|object}
@internal
###
inlineStyle = (element, props) ->
style = element.style
extractFromStyleObject(style, props)
extractFromStyleObject = (style, keyOrKeys) ->
if u.isString(keyOrKeys)
style[keyOrKeys]
else # array
u.only(style, keyOrKeys...)
###**
Sets the given CSS properties as inline styles on the given element.
@function up.element.setStyle
@param {Element} element
@param {Object} props
One or more CSS properties with kebab-case keys or camelCase keys.
@return {string|object}
@experimental
###
setInlineStyle = (element, props) ->
style = element.style
for key, value of props
value = normalizeStyleValueForWrite(key, value)
style[key] = value
normalizeStyleValueForWrite = (key, value) ->
if u.isMissing(value)
value = ''
else if CSS_LENGTH_PROPS.has(key.toLowerCase().replace(/-/, ''))
value = cssLength(value)
value
CSS_LENGTH_PROPS = u.arrayToSet [
'top', 'right', 'bottom', 'left',
'padding', 'paddingtop', 'paddingright', 'paddingbottom', 'paddingleft',
'margin', 'margintop', 'marginright', 'marginbottom', 'marginleft',
'borderwidth', 'bordertopwidth', 'borderrightwidth', 'borderbottomwidth', 'borderleftwidth'
'width', 'height',
'maxwidth', 'maxheight',
'minwidth', 'minheight',
]
###**
Converts the given value to a CSS length value, adding a `px` unit if required.
@function cssLength
@internal
###
cssLength = (obj) ->
if u.isNumber(obj) || (u.isString(obj) && /^\d+$/.test(obj))
obj.toString() + "px"
else
obj
###**
Resolves the given CSS selector (which might contain `&` references)
to a full CSS selector without ampersands.
If passed an `Element` or `jQuery` element, returns a CSS selector string
for that element.
@function up.element.resolveSelector
@param {string|Element|jQuery} selectorOrElement
@param {string|Element|jQuery} origin
The element that this selector resolution is relative to.
That element's selector will be substituted for `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
@return {string}
@internal
###
resolveSelector = (selectorOrElement, origin) ->
if u.isString(selectorOrElement)
selector = selectorOrElement
if u.contains(selector, '&')
if u.isPresent(origin) # isPresent returns false for empty jQuery collection
originSelector = toSelector(origin)
selector = selector.replace(/\&/, originSelector)
else
up.fail("Found origin reference (%s) in selector %s, but no origin was given", '&', selector)
else
selector = toSelector(selectorOrElement)
selector
###**
Returns whether the given element is currently visible.
An element is considered visible if it consumes space in the document.
Elements with `{ visibility: hidden }` or `{ opacity: 0 }` are considered visible, since they still consume space in the layout.
Elements not attached to the DOM are considered hidden.
@function up.element.isVisible
@param {Element} element
The element to check.
@experimental
###
isVisible = (element) ->
# From https://github.com/jquery/jquery/blame/9cb162f6b62b6d4403060a0f0d2065d3ae96bbcc/src/css/hiddenVisibleSelectors.js#L12
!!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)
<% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
# also document :has()!
first: first # same as document.querySelector
all: all # same as document.querySelectorAll
subtree: subtree # practical
closest: closest # needed for IE11
matches: matches # needed for IE11
ancestor: ancestor # not practical. we use it to implement closest
get: getOne # practical for code that also works with jQuery
list: getList # practical for composing multiple collections, or wrapping.
remove: remove # needed for IE11
toggle: toggle # practical
toggleClass: toggleClass # practical
hide: hide # practical
show: show # practical
metaContent: metaContent # internal
replace: replace # needed for IE11
insertBefore: insertBefore # internal shortcut, people can use insertAdjacentElement and i don't want to support insertAfter when I don't need it.
createFromSelector: createFromSelector # practical for element creation.
setAttrs: setAttrs # practical
affix: affix # practical for element creation
toSelector: toSelector # practical
isSingleton: isSingleton # internal
attributeSelector: attributeSelector # internal
createDocumentFromHtml: createDocumentFromHtml # internal
createFromHtml: createFromHtml # practical for element creation
root: getRoot # internal
paint: paint # internal
concludeCssTransition: concludeCssTransition # internal
hasCssTransition: hasCssTransition # internal
fixedToAbsolute: fixedToAbsolute # internal
setMissingAttrs: setMissingAttrs # internal
unwrap: unwrap # practical for jQuery migration
# presentAttr: presentAttr # experimental
booleanAttr: booleanAttr # it's practical, but i cannot find a good name. people might expect it to cast to number, too. but i don't need that for my own code. maybe booleanAttr?
numberAttr: numberAttr # practical
jsonAttr: jsonAttr # practical
booleanOrStringAttr: booleanOrStringAttr
setTemporaryStyle: setTemporaryStyle # practical
style: computedStyle # practical.
styleNumber: computedStyleNumber # practical.
inlineStyle: inlineStyle # internal
setStyle: setInlineStyle # practical.
resolveSelector: resolveSelector # internal
none: -> NONE # internal
isVisible: isVisible # practical