diff --git a/README.md b/README.md index 4048004..77f1412 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 + +## 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: '
' +}) +``` diff --git a/dom/index.js b/dom/index.js index 9614c7a..f4c43f6 100644 --- a/dom/index.js +++ b/dom/index.js @@ -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 diff --git a/html/createElement.js b/html/createElement.js new file mode 100644 index 0000000..2b5706e --- /dev/null +++ b/html/createElement.js @@ -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 +} diff --git a/karma.conf.js b/karma.conf.js index bfecb97..4c01376 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -22,6 +22,7 @@ const cfg = { include: [ path.join(__dirname, 'lib'), path.join(__dirname, 'dom'), + path.join(__dirname, 'html'), path.join(__dirname, 'test') ], use: [ @@ -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' } ] diff --git a/lib/wrapInArray.js b/lib/wrapInArray.js new file mode 100644 index 0000000..ef875b5 --- /dev/null +++ b/lib/wrapInArray.js @@ -0,0 +1,3 @@ +module.exports = function wrapInArray (value) { + return !Array.isArray(value) ? [value] : value +} diff --git a/test/dom.js b/test/dom/dom.js similarity index 99% rename from test/dom.js rename to test/dom/dom.js index 5a3ab95..b4c0d59 100644 --- a/test/dom.js +++ b/test/dom/dom.js @@ -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') diff --git a/test/html/createElement.js b/test/html/createElement.js new file mode 100644 index 0000000..4d6332a --- /dev/null +++ b/test/html/createElement.js @@ -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 = '

the cat jumped over the moon

' + const element = createElement({ + type: 'div', + innerHTML: div.outerHTML + }) + expect(element.innerHTML).equal(innerHTML) + expect(element.children[0].nodeName).equal('P') + }) + }) +}) diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..dc5a499 --- /dev/null +++ b/test/index.js @@ -0,0 +1,6 @@ +require('./html/createElement') +require('./dom/dom') +require('./lib/once') +require('./lib/promised') +require('./lib/withRestoreAll') +require('./lib/wrapInArray.js') diff --git a/test/once.js b/test/lib/once.js similarity index 91% rename from test/once.js rename to test/lib/once.js index bf0e8ba..ab4476c 100644 --- a/test/once.js +++ b/test/lib/once.js @@ -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') diff --git a/test/promised.js b/test/lib/promised.js similarity index 96% rename from test/promised.js rename to test/lib/promised.js index 5672bad..91e7332 100644 --- a/test/promised.js +++ b/test/lib/promised.js @@ -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') diff --git a/test/withRestoreAll.js b/test/lib/withRestoreAll.js similarity index 95% rename from test/withRestoreAll.js rename to test/lib/withRestoreAll.js index af0baa0..434eb4a 100644 --- a/test/withRestoreAll.js +++ b/test/lib/withRestoreAll.js @@ -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') diff --git a/test/lib/wrapInArray.js b/test/lib/wrapInArray.js new file mode 100644 index 0000000..70502e8 --- /dev/null +++ b/test/lib/wrapInArray.js @@ -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]) + }) +})