Skip to content
This repository has been archived by the owner on Nov 17, 2021. It is now read-only.

Commit

Permalink
fix(Utility function): Better type safety and more flexibility for cr…
Browse files Browse the repository at this point in the history
…eate and append
  • Loading branch information
nokome committed Feb 26, 2020
1 parent 5908c8a commit 7ef4cdd
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
16 changes: 13 additions & 3 deletions src/util/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,18 @@ describe('create', () => {
class: 'bar',
attr1: 'baz',
attr2: 42,
attr3: undefined
attr3: undefined,
attr4: true,
attr5: false
})

expect(elem.id).toEqual('foo')
expect(elem.className).toEqual('bar')
expect(elem.getAttribute('attr1')).toEqual('baz')
expect(elem.getAttribute('attr2')).toEqual('42')
expect(elem.getAttribute('attr3')).toEqual(null)
expect(elem.getAttribute('attr4')).toEqual('true')
expect(elem.getAttribute('attr5')).toEqual('false')
})

it.each([
Expand All @@ -230,8 +234,14 @@ describe('create', () => {
expect(elem.getAttribute('attr2')).toEqual('zot')
})

it('can be passed child elements', () => {
const elem = create('div', create('span'), create('img'))
it('can be passed child elements; undefineds ignored', () => {
const elem = create(
'div',
undefined,
create('span'),
undefined,
create('img')
)
expect(elem.outerHTML).toEqual('<div><span></span><img></div>')
})
})
Expand Down
37 changes: 22 additions & 15 deletions src/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ export function select(...args: (string | Document | Element)[]): Element[] {
*/
export function create(
spec: string | Element = 'div',
...children: (object | string | number | Element)[]
attrs?:
| Record<string, undefined | boolean | number | string>
| (undefined | boolean | number | string | Element),
...children: (undefined | boolean | number | string | Element)[]
): Element {
let elem: Element
if (spec instanceof Element) {
Expand Down Expand Up @@ -220,22 +223,17 @@ export function create(
})
}

// If the first child is an object then use it to
// set attributes.
const first = children[0]
if (typeof first === 'object' && !(first instanceof Element)) {
Object.entries(first).forEach(([key, value]) => {
if (value !== undefined) elem.setAttribute(key, value)
// If the attrs arg is a Record then use it, otherwise add it to children
if (typeof attrs === 'object' && !(attrs instanceof Element)) {
Object.entries(attrs).forEach(([key, value]) => {
if (value !== undefined) elem.setAttribute(key, `${value}`)
})
children = children.slice(1)
} else if (attrs !== undefined) {
children = [attrs as typeof children[0], ...children]
}

// Append children as elements or text
children.forEach(item =>
elem.appendChild(
item instanceof Element ? item : document.createTextNode(`${item}`)
)
)
children.forEach(item => append(elem, item))

return elem
}
Expand Down Expand Up @@ -300,8 +298,17 @@ export function text(
* @param {Element} target The element to append to
* @param {...Element} elems The elements to append
*/
export function append(target: Element, ...elems: Element[]): void {
elems.forEach(elem => target.appendChild(elem))
export function append(
target: Element,
...elems: (undefined | boolean | number | string | Element)[]
): void {
elems.forEach(elem =>
elem !== undefined
? target.appendChild(
elem instanceof Element ? elem : document.createTextNode(`${elem}`)
)
: undefined
)
}

/**
Expand Down

0 comments on commit 7ef4cdd

Please sign in to comment.