diff --git a/packages/metal-dom/src/domNamed.js b/packages/metal-dom/src/domNamed.js index 4e10534b..9d3c64c6 100644 --- a/packages/metal-dom/src/domNamed.js +++ b/packages/metal-dom/src/domNamed.js @@ -521,6 +521,34 @@ export function parent(element, selector) { return closest(element.parentNode, selector); } +/** + * Inserts a node before first child of the parent. If child is a HTML string + * it will be converted to document fragment before prepending it to the parent. + * @param {!Element} parent The node to prepend to. + * @param {!(Element|NodeList|string)} child The thing who must be prepended + * @return {!Element} The prepended child + */ +export function prepend(parent, child) { + if (isString(child)) { + child = buildFragment(child); + } + + if (!isNodeListLike(child) && !isDefAndNotNull(parent.firstChild)) { + return append(parent, child); + } + + if (isNodeListLike(child)) { + const childArr = Array.prototype.slice.call(child); + for (let i = childArr.length - 1; i >= 0; i--) { + parent.insertBefore(childArr[i], parent.firstChild); + } + } else { + parent.insertBefore(child, parent.firstChild); + } + + return child; +} + /** * Registers a custom event. * @param {string} eventName The name of the custom event. diff --git a/packages/metal-dom/test/dom.js b/packages/metal-dom/test/dom.js index 3d98ae8d..fc48f160 100644 --- a/packages/metal-dom/test/dom.js +++ b/packages/metal-dom/test/dom.js @@ -215,6 +215,83 @@ describe('dom', function() { assert.strictEqual('myChild2', parent.childNodes[1].className); }); + it('should prepend an element into a div without first child', function() { + let parent = document.createElement('div'); + let elem = dom.buildFragment('

Hello World

'); + + dom.prepend(parent, elem); + + assert.strictEqual('

Hello World

', parent.innerHTML); + }); + + it('should prepend an element into a div', function() { + let parent = document.createElement('div'); + let p = document.createElement('p'); + let span = document.createElement('span'); + + dom.append(parent, p); + dom.prepend(parent, span); + + assert.strictEqual(parent.innerHTML, '

'); + }); + + it('should prepend a text into a div', function() { + let parent = document.createElement('div'); + + dom.append(parent, 'Some text'); + dom.prepend(parent, 'Headline: '); + + assert.strictEqual(parent.innerHTML, 'Headline: Some text'); + }); + + it('should prepend a node list to parent element', function() { + let parent = document.createElement('div'); + + let childFrag = dom.buildFragment( + '
el1
el2
el3
' + ); + + dom.prepend(parent, childFrag.childNodes); + + assert.strictEqual(3, parent.childNodes.length); + assert.strictEqual('myChild', parent.childNodes[0].className.trim()); + assert.strictEqual('myChild2', parent.childNodes[1].className.trim()); + assert.strictEqual('myChild3', parent.childNodes[2].className.trim()); + + let parent2 = document.createElement('div'); + + dom.prepend( + parent2, + dom.buildFragment( + '
' + ).childNodes + ); + dom.prepend(parent2, dom.buildFragment('
')); + + assert.strictEqual(4, parent2.childNodes.length); + assert.strictEqual('container', parent2.childNodes[0].className.trim()); + assert.strictEqual('myChild', parent2.childNodes[1].className.trim()); + assert.strictEqual('myChild2', parent2.childNodes[2].className.trim()); + assert.strictEqual('myChild3', parent2.childNodes[3].className.trim()); + + let parent3 = document.createElement('div'); + let child = document.createElement('div'); + + dom.addClasses(child, 'child'); + dom.append(parent3, child); + + let childFrag2 = dom.buildFragment( + '
el1
el2
el3
' + ); + + dom.prepend(parent3, childFrag2.childNodes); + assert.strictEqual(4, parent3.childNodes.length); + assert.strictEqual('myChild', parent3.childNodes[0].className.trim()); + assert.strictEqual('myChild2', parent3.childNodes[1].className.trim()); + assert.strictEqual('myChild3', parent3.childNodes[2].className.trim()); + assert.strictEqual('child', parent3.childNodes[3].className.trim()); + }); + it('should replace an element with a requested element', function() { let element1 = document.createElement('div'); let element2 = document.createElement('div');