UNPKG

ember-app-scheduler

Version:

Ember addon to schedule work at different phases of app life cycle.

79 lines 3.38 kB
import { ConcreteBounds } from '../bounds'; import { moveNodesBefore } from '../dom/helper'; 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, DOMChangesClass) { if (!document) return DOMChangesClass; if (!shouldApplyFix(document)) { return DOMChangesClass; } let div = document.createElement('div'); return class DOMChangesWithInnerHTMLFix extends DOMChangesClass { insertHTMLBefore(parent, nextSibling, html) { 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, DOMTreeConstructionClass) { if (!document) return DOMTreeConstructionClass; if (!shouldApplyFix(document)) { return DOMTreeConstructionClass; } let div = document.createElement('div'); return class DOMTreeConstructionWithInnerHTMLFix extends DOMTreeConstructionClass { insertHTMLBefore(parent, referenceNode, html) { if (html === null || html === '') { return super.insertHTMLBefore(parent, referenceNode, html); } let parentTag = parent.tagName.toLowerCase(); let wrapper = innerHTMLWrapper[parentTag]; if (wrapper === undefined) { return super.insertHTMLBefore(parent, referenceNode, html); } return fixInnerHTML(parent, wrapper, div, html, referenceNode); } }; } function fixInnerHTML(parent, wrapper, div, html, reference) { let wrappedHtml = wrapper.before + html + wrapper.after; div.innerHTML = wrappedHtml; let parentNode = 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) { 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; }