element-props
Version:
Normalize access to element attributes/properties
126 lines (85 loc) • 3.73 kB
Markdown
# element-props <!--[](https://travis-ci.org/spectjs/element-props)--> [](https://github.com/spectjs/element-props/actions/workflows/test.yml) [](https://bundlephobia.com/result?p=element-props)
Normalize access to element attributes/properties.
[](https://nodei.co/npm/element-props/)
```js
import elementProps from 'element-props.js'
let el = document.getElementById('my-element')
props = elementProps(el, { z: Number })
// numeric
props.x = 1
el.getAttribute('x') // '1'
props.x // 1
// boolean
el.setAttribute('disabled', '')
props.disabled // true
props.disabled = false
el.getAttribute('disabled') // 'false'
props.disabled = null
el.getAttribute('disabled') // null
// functions
props.onclick = e => ()
// spread
{...props} // { y: false, x: 1, id: 'my-element' }
```
## API
### props = elementProps(element, types?, onchange?)
Create `props` for an `element`, with optional `types = { propName: Type }` (compat. with [attr-types](https://github.com/qwtel/attr-types)).<br/>
_Type_ is any data class like _Number_, _Boolean_, _String_, _Array_, _Object_, _Data_, _RegExp_, or `string => data` function like _JSON.parse_ (used for _Array_ and _Object_).
```js
import elementProps from 'element-props';
let props = elementProps(el, {n:Number, b:Boolean, o:Object, a:Array, s:String, d:Date}, (key, val) => {})
props.n = '1'
el.setAttribute('b', '')
el.s = 'abc'
el.setAttribute('a', '1,2,3')
el.setAttribute('o', '{foo:"bar"}')
{...props} // {n: 1, b: true, s: 'abc', o: {foo:'bar'}, a: [1,2,3]}
```
`props` handle input elements - _text_, _checkbox_, _select_:
```js
let el = document.querySelector('#checkbox')
let props = elementProps(el)
props.value = true
el.value // 'on'
el.checked // true
props.value // true
el.getAttribute('value') // 'on'
el.getAttribute('checked') // ''
```
### prop(el, key, value)
Set `key` prop/attribute value depending on value type.
* `on*` property can only be a function.
* `onEvt` === `onevt`.
* `style` can only be an object or a string.
* `class` can be a string, object or a string.
* `id` can only be a string.
* Empty strings are considered booleans: `<a disabled />` → `a.props.disabled === true`
CamelCase key name is mapped to dash-case for attribute.
### [get, set] = input(el)
Create getter/setter for an input depending on element type.
### value = parse(string, Type?)
Convert string value into defined type _or_ detect type automatically (tiny _auto-parse_).
```js
import { parse } from './element-props.js'
parse('true', Boolean) // true
parse('123') // 123
parse('1,2,3', Array) // [1, 2, 3]
parse('{ a: 1, b: 2 }', Object) // { a: 1, b: 2}
```
### polyfill
Add `props` to all HTML elements by including augment for `Element.prototype.props`:
```js
import 'element-props/augment.js'
document.body.id = 'my-body'
document.body.props // { id: 'my-body' }
```
### Design
Internally uses _Proxy_, (no IE11 support, but in theory possible with _MutationObserver_ fallback)
Inspired by this [tweet](https://twitter.com/WebReflection/status/1260948278977409026?s=20) with spreading [hint](https://github.com/tc39/proposal-object-rest-spread/issues/69#issuecomment-633232470).
## See also
* [Element properties proposal](https://github.com/developit/unified-element-properties-proposal)
* [templize](https://github.com/spectjs/templize)
* [attr-types](https://github.com/qwtel/attr-types)
## License
ISC © Dmitry Iv.
<p align="center">ॐ</p>