Skip to content

Commit

Permalink
Add prepend function
Browse files Browse the repository at this point in the history
  • Loading branch information
demiazz committed Jun 7, 2017
1 parent 2e13acd commit fe4846a
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 1 deletion.
2 changes: 2 additions & 0 deletions d.ts/homey.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type CSSSelector = string;
export type Dataset = { [key: string]: string };
export type Elements = Element[];
export type EventType = string;
export type Insertable = string | Node | NodeList;

type EventOptions = { bubbles?: boolean, cancelable?: boolean, detail?: any };
type Predicate = (element: Element) => boolean;
Expand Down Expand Up @@ -38,6 +39,7 @@ export function delegate(target: EventTarget, selector: CSSSelector, eventType:

/* Manipulation */

export function prepend(element: Element, ...insertable: Insertable[]): void;
export function remove(element: Element): boolean;
export function setHtml(element: Element, html: string): void;
export function setText(element: Node, text: string): void;
Expand Down
212 changes: 212 additions & 0 deletions spec/manipulation/prepend.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import { prepend } from "../../src";

describe("prepend", () => {
afterEach(clearFixtures);

it("inserts given HTML string to begin of element", () => {
useFixture(`
<div class="root">
<span>Existing Node</span>
</div>
`);

const subject = document.querySelector(".root");

prepend(subject, "Text Node<span>Span Node</span>");

const nodes = getSignificantNodes(subject);

expect(nodes.length).toBe(3);

expect(nodes[0]).toBeTextNode();
expect(nodes[0]).toHaveText("Text Node");

expect(nodes[1]).toBeElementNode();
expect(nodes[1]).toBeTag("span");
expect(nodes[1]).toHaveText("Span Node");

expect(nodes[2]).toBeElementNode();
expect(nodes[2]).toBeTag("span");
expect(nodes[2]).toHaveText("Existing Node");
});

it("inserts given node to begin of element", () => {
useFixture(`
<div class="root">
Text Node
<span>Existing Node</span>
</div>
`);

const textNode = document.createTextNode("New Text Node");
const elementNode = document.createElement("span");
const subject = document.querySelector(".root");

elementNode.textContent = "Span Node";

prepend(subject, elementNode);
prepend(subject, textNode);

const nodes = getSignificantNodes(subject);

expect(nodes.length).toBe(4);

expect(nodes[0]).toBeTextNode();
expect(nodes[0]).toHaveText("New Text Node");

expect(nodes[1]).toBeElementNode();
expect(nodes[1]).toBeTag("span");
expect(nodes[1]).toHaveText("Span Node");

expect(nodes[2]).toBeTextNode();
expect(nodes[2]).toHaveText("Text Node");

expect(nodes[3]).toBeElementNode();
expect(nodes[3]).toBeTag("span");
expect(nodes[3]).toHaveText("Existing Node");
});

it("inserts given nodes from node list to begin of element", () => {
useFixture(`
<div class="root">
Text Node
<span>Existing Node</span>
</div>
`);

const fragment = document.createDocumentFragment();
const textNode = document.createTextNode("New Text Node");
const elementNode = document.createElement("span");

fragment.appendChild(textNode);
fragment.appendChild(elementNode);

elementNode.textContent = "Span Node";

const subject = document.querySelector(".root");

prepend(subject, fragment.childNodes);

const nodes = getSignificantNodes(subject);

expect(nodes.length).toBe(4);

expect(nodes[0]).toBeTextNode();
expect(nodes[0]).toHaveText("New Text Node");

expect(nodes[1]).toBeElementNode();
expect(nodes[1]).toBeTag("span");
expect(nodes[1]).toHaveText("Span Node");

expect(nodes[2]).toBeTextNode();
expect(nodes[2]).toHaveText("Text Node");

expect(nodes[3]).toBeElementNode();
expect(nodes[3]).toBeTag("span");
expect(nodes[3]).toHaveText("Existing Node");
});

it("inserts given document fragment to begin of element", () => {
useFixture(`
<div class="root">
Text Node
<span>Existing Node</span>
</div>
`);

const fragment = document.createDocumentFragment();
const textNode = document.createTextNode("New Text Node");
const elementNode = document.createElement("span");

fragment.appendChild(textNode);
fragment.appendChild(elementNode);

elementNode.textContent = "Span Node";

const subject = document.querySelector(".root");

prepend(subject, fragment);

const nodes = getSignificantNodes(subject);

expect(nodes.length).toBe(4);

expect(nodes[0]).toBeTextNode();
expect(nodes[0]).toHaveText("New Text Node");

expect(nodes[1]).toBeElementNode();
expect(nodes[1]).toBeTag("span");
expect(nodes[1]).toHaveText("Span Node");

expect(nodes[2]).toBeTextNode();
expect(nodes[2]).toHaveText("Text Node");

expect(nodes[3]).toBeElementNode();
expect(nodes[3]).toBeTag("span");
expect(nodes[3]).toHaveText("Existing Node");
});

it("inserts given multiple arguments to begin of element", () => {
useFixture(`
<div class="root">
Text Node
<span>Existing Node</span>
</div>
`);

const html = "HTML Text Node<span>Span from HTML</span>";
const standaloneTextNode = document.createTextNode("Standalone Text Node");
const standaloneElementNode = document.createElement("span");
const fragment = document.createDocumentFragment();
const textNode = document.createTextNode("Text Node from NodeList");
const elementNode = document.createElement("span");

standaloneElementNode.textContent = "Standalone Element Node";
elementNode.textContent = "Element Node from NodeList";

fragment.appendChild(textNode);
fragment.appendChild(elementNode);

const subject = document.querySelector(".root");

prepend(
subject,
html,
standaloneTextNode,
standaloneElementNode,
fragment.childNodes
);

const nodes = getSignificantNodes(subject);

expect(nodes.length).toBe(8);

expect(nodes[0]).toBeTextNode();
expect(nodes[0]).toHaveText("HTML Text Node");

expect(nodes[1]).toBeElementNode();
expect(nodes[1]).toBeTag("span");
expect(nodes[1]).toHaveText("Span from HTML");

expect(nodes[2]).toBeTextNode();
expect(nodes[2]).toHaveText("Standalone Text Node");

expect(nodes[3]).toBeElementNode();
expect(nodes[3]).toBeTag("span");
expect(nodes[3]).toHaveText("Standalone Element Node");

expect(nodes[4]).toBeTextNode();
expect(nodes[4]).toHaveText("Text Node from NodeList");

expect(nodes[5]).toBeElementNode();
expect(nodes[5]).toBeTag("span");
expect(nodes[5]).toHaveText("Element Node from NodeList");

expect(nodes[6]).toBeTextNode();
expect(nodes[6]).toHaveText("Text Node");

expect(nodes[7]).toBeElementNode();
expect(nodes[7]).toBeTag("span");
expect(nodes[7]).toHaveText("Existing Node");
});
});
6 changes: 5 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
DelegateEventHandler,
EventType
} from "./events/types";
import type { Insertable } from "./manipulation/types";
import type { CSSSelector, Elements } from "./types";

import body from "./aliases/body";
Expand All @@ -24,6 +25,7 @@ import delegate from "./events/delegate";
import dispatch from "./events/dispatch";
import on from "./events/on";
import once from "./events/once";
import prepend from "./manipulation/prepend";
import remove from "./manipulation/remove";
import setHtml from "./manipulation/set-html";
import setText from "./manipulation/set-text";
Expand All @@ -47,7 +49,8 @@ export type {
DelegateEvent,
DelegateEventHandler,
Elements,
EventType
EventType,
Insertable
};

export {
Expand All @@ -65,6 +68,7 @@ export {
dispatch,
on,
once,
prepend,
remove,
setHtml,
setText,
Expand Down
34 changes: 34 additions & 0 deletions src/manipulation/prepend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* @flow */

import type { Insertable } from "./types";

import { toArray } from "../utils";

function prependString(element: Element, insertable: string): void {
element.insertAdjacentHTML("afterbegin", insertable);
}

function prependNode(element: Element, insertable: Node): void {
element.insertBefore(insertable, element.firstChild);
}

function prependNodeList(element: Element, insertable: NodeList<*>): void {
toArray(insertable).reverse().forEach(node => {
prependNode(element, node);
});
}

export default function prepend(
element: Element,
...insertables: Array<Insertable>
): void {
insertables.reverse().forEach(insertable => {
if (typeof insertable === "string") {
prependString(element, insertable);
} else if (insertable instanceof Node) {
prependNode(element, insertable);
} else {
prependNodeList(element, insertable);
}
});
}
3 changes: 3 additions & 0 deletions src/manipulation/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* @flow */

export type Insertable = string | Node | NodeList<*>;

0 comments on commit fe4846a

Please sign in to comment.