Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Utilities for clientside code injection

This repo contains these sets

- @qubit/utils/dom
- @qubit/utils/html

Each as a different purpose and should be required in separately as required to avoid build bloat

### @qubit/utils/dom

## Usage
Expand Down Expand Up @@ -154,3 +161,28 @@ Functionality is the same as described in https://developer.mozilla.org/en-US/do
```js
const closestElement = closest(targetElement, selectors)
```

### @qubit/html
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@qubit/html would be a different package right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if it should be part of utils because it is directly related to html element creation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right but the name @qubit/html implies a separate package, did you mean @qubit/utils/html?


## Usage

```js
const { createElement } = require('@qubit/html/createElement')
```

## createElement()

Creates the specified html element and adds on attributes if supplied.
The function exposes a configuration based interface for element creation

```js
const badge = createElement({
type: 'div',
id: 'qp-RFfz2OIZSN',
classList: ['qp-badge', 'QubitPlacement'],
onClick: () => {
console.log('Danger Will Robinson')
},
innerHTML: '<div/>'
})
```
3 changes: 2 additions & 1 deletion dom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ function closest (element, selector) {
if (window.Element.prototype.closest) {
return window.Element.prototype.closest.call(element, selector)
} else {
const matches = window.Element.prototype.matches ||
const matches =
window.Element.prototype.matches ||
window.Element.prototype.msMatchesSelector ||
window.Element.prototype.webkitMatchesSelector

Expand Down
22 changes: 22 additions & 0 deletions html/createElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const wrapInArray = require('../lib/wrapInArray')

module.exports = function createElement ({
type,
id,
classList,
onClick,
innerHTML
}) {
const element = document.createElement(type)

if (id) element.setAttribute('id', id)
if (classList) {
for (const className of wrapInArray(classList)) {
element.classList.add(className)
}
}
if (onClick) element.onclick = onClick
if (innerHTML) element.innerHTML = innerHTML

return element
}
7 changes: 6 additions & 1 deletion karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const cfg = {
include: [
path.join(__dirname, 'lib'),
path.join(__dirname, 'dom'),
path.join(__dirname, 'html'),
path.join(__dirname, 'test')
],
use: [
Expand Down Expand Up @@ -58,7 +59,11 @@ function enableCoverage (cfg) {
cfg.webpack.module.rules = [
{
test: /\.js$/,
include: [path.join(__dirname, 'lib'), path.join(__dirname, 'dom')],
include: [
path.join(__dirname, 'lib'),
path.join(__dirname, 'dom'),
path.join(__dirname, 'html')
],
loader: 'istanbul-instrumenter-loader'
}
]
Expand Down
3 changes: 3 additions & 0 deletions lib/wrapInArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function wrapInArray (value) {
return !Array.isArray(value) ? [value] : value
}
2 changes: 1 addition & 1 deletion test/dom.js → test/dom/dom.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* globals describe it beforeEach afterEach */
const Promise = require('sync-p')
const _ = require('slapdash')
const dom = require('../dom')
const dom = require('../../dom')
const sinon = require('sinon')
const { expect } = require('chai')

Expand Down
73 changes: 73 additions & 0 deletions test/html/createElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* globals describe it */
const createElement = require('../../html/createElement')
const { expect } = require('chai')

describe('HTML element create helpers', function () {
describe('createElement function creates a HTML element matching config object', function () {
;[['div', 'DIV'], ['a', 'A'], ['p', 'P'], ['h1', 'H1']].forEach(
([request, expected]) => {
const title = `creates requested ${request} HTML element`
it(title, function () {
const element = createElement({
type: request
})
expect(element.nodeName).equal(expected)
})
}
)

it('appends an id to the element', function () {
const ID = 'ajfoij2902cfv'
const element = createElement({
type: 'div',
id: ID
})
expect(element.id).equal(ID)
})

it('appends a single class to an element', function () {
const CLASS_EXAMPLE = 'qp-badge'
const element = createElement({
type: 'div',
classList: CLASS_EXAMPLE
})
expect(element.classList.contains(CLASS_EXAMPLE)).to.equal(true)
})

it('appends an array of classes to an element', function () {
const CLASS_EXAMPLE = ['qp-badge', 'qp-wrapper']
const element = createElement({
type: 'div',
classList: CLASS_EXAMPLE
})
expect(element.classList.contains(CLASS_EXAMPLE[0])).to.equal(true)
expect(element.classList.contains(CLASS_EXAMPLE[1])).to.equal(true)
})

it('appends an onclick handler to the element', function () {
const onClick = function () {
return 'ALPHA'
}
const element = createElement({
type: 'div',
onClick
})
expect(element.onclick).equal(onClick)
expect(element.onclick()).equal(onClick())
})

it('adds innerHTML to the element', function () {
const text = 'the cat jumped over the moon'
const textNode = document.createTextNode(text)
const div = document.createElement('p')
div.appendChild(textNode)
const innerHTML = '<p>the cat jumped over the moon</p>'
const element = createElement({
type: 'div',
innerHTML: div.outerHTML
})
expect(element.innerHTML).equal(innerHTML)
expect(element.children[0].nodeName).equal('P')
})
})
})
6 changes: 6 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require('./html/createElement')
require('./dom/dom')
require('./lib/once')
require('./lib/promised')
require('./lib/withRestoreAll')
require('./lib/wrapInArray.js')
2 changes: 1 addition & 1 deletion test/once.js → test/lib/once.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* globals describe it */
const once = require('../lib/once')
const once = require('../../lib/once')
const sinon = require('sinon')
const { expect } = require('chai')

Expand Down
2 changes: 1 addition & 1 deletion test/promised.js → test/lib/promised.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* globals describe it */
const promised = require('../lib/promised')
const promised = require('../../lib/promised')
const sinon = require('sinon')
const { expect } = require('chai')

Expand Down
2 changes: 1 addition & 1 deletion test/withRestoreAll.js → test/lib/withRestoreAll.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* globals describe it */
const withRestoreAll = require('../lib/withRestoreAll')
const withRestoreAll = require('../../lib/withRestoreAll')
const sinon = require('sinon')
const { expect } = require('chai')

Expand Down
15 changes: 15 additions & 0 deletions test/lib/wrapInArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* globals describe it */
const { expect } = require('chai')
const wrapInArray = require('../../lib/wrapInArray')

describe('wrapInArray', function () {
it('should wrap value in array', function () {
const wrapped = wrapInArray(5)
expect(wrapped).to.eql([5])
})

it('should wrap once', function () {
const wrapped = wrapInArray([42])
expect(wrapped).to.eql([42])
})
})