UNPKG

ember-material-icons

Version:

Google Material icons for your ember-cli app

110 lines (86 loc) 3.61 kB
import { Bounds, ConcreteBounds } from '../bounds'; import { moveNodesBefore, DOMChanges, DOMTreeConstruction } from '../dom/helper'; import { Option } from '@glimmer/util'; interface Wrapper { depth: number; before: string; after: string; } let innerHTMLWrapper = { colgroup: { depth: 2, before: '<table><colgroup>', after: '</colgroup></table>' }, table: { depth: 1, before: '<table>', after: '</table>' }, tbody: { depth: 2, before: '<table><tbody>', after: '</tbody></table>' }, tfoot: { depth: 2, before: '<table><tfoot>', after: '</tfoot></table>' }, thead: { depth: 2, before: '<table><thead>', after: '</thead></table>' }, tr: { depth: 3, before: '<table><tbody><tr>', after: '</tr></tbody></table>' } }; // Patch: innerHTML Fix // Browsers: IE9 // Reason: IE9 don't allow us to set innerHTML on col, colgroup, frameset, // html, style, table, tbody, tfoot, thead, title, tr. // Fix: Wrap the innerHTML we are about to set in its parents, apply the // wrapped innerHTML on a div, then move the unwrapped nodes into the // target position. export function domChanges(document: Option<Document>, DOMChangesClass: typeof DOMChanges): typeof DOMChanges { if (!document) return DOMChangesClass; if (!shouldApplyFix(document)) { return DOMChangesClass; } let div = document.createElement('div'); return class DOMChangesWithInnerHTMLFix extends DOMChangesClass { insertHTMLBefore(parent: HTMLElement, nextSibling: Node, html: string): Bounds { if (html === null || html === '') { return super.insertHTMLBefore(parent, nextSibling, html); } let parentTag = parent.tagName.toLowerCase(); let wrapper = innerHTMLWrapper[parentTag]; if(wrapper === undefined) { return super.insertHTMLBefore(parent, nextSibling, html); } return fixInnerHTML(parent, wrapper, div, html, nextSibling); } }; } export function treeConstruction(document: Option<Document>, DOMTreeConstructionClass: typeof DOMTreeConstruction): typeof DOMTreeConstruction { if (!document) return DOMTreeConstructionClass; if (!shouldApplyFix(document)) { return DOMTreeConstructionClass; } let div = document.createElement('div'); return class DOMTreeConstructionWithInnerHTMLFix extends DOMTreeConstructionClass { insertHTMLBefore(parent: HTMLElement, html: string, reference: Node): Bounds { if (html === null || html === '') { return super.insertHTMLBefore(parent, html, reference); } let parentTag = parent.tagName.toLowerCase(); let wrapper = innerHTMLWrapper[parentTag]; if(wrapper === undefined) { return super.insertHTMLBefore(parent, html, reference); } return fixInnerHTML(parent, wrapper, div, html, reference); } }; } function fixInnerHTML(parent: HTMLElement, wrapper: Wrapper, div: HTMLElement, html: string, reference: Node): Bounds { let wrappedHtml = wrapper.before + html + wrapper.after; div.innerHTML = wrappedHtml; let parentNode: Node = div; for (let i=0; i<wrapper.depth; i++) { parentNode = parentNode.childNodes[0]; } let [first, last] = moveNodesBefore(parentNode, parent, reference); return new ConcreteBounds(parent, first, last); } function shouldApplyFix(document: Document) { let table = document.createElement('table'); try { table.innerHTML = '<tbody></tbody>'; } catch (e) { } finally { if (table.childNodes.length !== 0) { // It worked as expected, no fix required return false; } } return true; }