$30 off During Our Annual Pro Sale. View Details »

The Giving Tree

The Giving Tree

DOM Talk given at EmpireJS 2015

Mark Wunsch

April 27, 2015
Tweet

More Decks by Mark Wunsch

Other Decks in Programming

Transcript

  1. The Giving Tree
    @markwunsch

    View Slide

  2. View Slide

  3. The Ash Yggdrasil
    Friedrich Wilhelm Heine, 1886

    View Slide

  4. Document
    Object
    Model

    View Slide

  5. Document Object Model (DOM) Level 1 Specification
    http://www.w3.org/TR/REC-DOM-Level-1/
    In the DOM, documents have a logical
    structure which is very much like a tree; to be
    more precise, it is like a “forest” or “grove”,
    which can contain more than one tree.
    However, the DOM does not specify that
    documents must be implemented as a tree or a
    grove, nor does it specify how the relationships
    among objects be implemented.

    View Slide

  6. What the Document Object Model is not
    • “…it does not implement all of ‘Dynamic HTML’.”
    • “The Document Object Model is not a binary specification.”
    • “The Document Object Model is not a way of persisting objects to XML
    or HTML.”
    • “The Document Object Model is not a set of data structures, it is an
    object model that specifies interfaces.”
    • “The Document Object Model does not define ‘the true inner semantics’
    of XML or HTML.”
    • “The Document Object Model…is not a competitor to the Component
    Object Model (COM).”

    View Slide

  7. $

    View Slide

  8. Closer to the
    METAL

    View Slide

  9. window.document

    View Slide

  10. TreeWalker

    View Slide

  11. document.createTreeWalker()

    View Slide

  12. createTreeWalker(root, whatToShow, filter)
    root, whatToShow, filter

    View Slide

  13. Document Object Model (DOM) Level 2 Traversal and Range Specification
    http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
    TreeWalker objects are used to navigate a
    document tree or subtree using the view of the
    document defined by their whatToShow flags
    and filter (if any).

    View Slide

  14. depth first
    pre-order

    View Slide

  15. HEADER
    HGROUP
    H2
    H1
    SECTION FOOTER
    DIV
    BODY
    1
    2
    3
    4
    5 6
    7 8

    View Slide

  16. var
    walker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    function (n) {
    return NodeFilter.FILTER_ACCEPT;
    });
    do {
    doSomething(walker.currentNode);
    } while (walker.nextNode());

    View Slide

  17. function getLegitTextNodes(el, f) {
    var
    blacklist = [‘SCRIPT’,‘OPTION’,‘TEXTAREA’],
    filter = function (node) {
    var parentName = node.parentElement.nodeName.toUpperCase();
    if (blacklist.indexOf(parentName) >= 0) {
    return NodeFilter.FILTER_REJECT;
    }
    if (!node.NodeValue.trim().length) {
    return NodeFilter.FILTER_SKIP;
    }
    return NodeFilter.FILTER_ACCEPT;
    },
    walker = document.createTreeWalker(
    el,
    NodeFilter.SHOW_TEXT,
    filter);
    while(walker.nextNode()) f(walker.currentNode);
    }
    https://gist.github.com/mwunsch/4710561

    View Slide

  18. console.log("digraph El {");
    do {
    var parentEl = walker.currentNode.parentElement;
    if (parentEl) {
    console.log(“\t\""+
    vizLabel(parentEl)+”\"->\""+
    vizLabel(walker.currentNode)+
    "\";");
    } else {
    console.log(“\t\""+
    vizLabel(walker.currentNode)+
    "\";");
    }
    } while (walker.nextNode());
    console.log("}");
    https://gist.github.com/mwunsch/6b538a0352cae834457a

    View Slide

  19. $ phantomjs viz.js http://2015.empirejs.org/ | dot -Tpng empire.png
    https://gist.github.com/mwunsch/6b538a0352cae834457a

    View Slide

  20. https://gist.github.com/mwunsch/6b538a0352cae834457a

    View Slide

  21. DocumentFragment

    View Slide

  22. document.createDocumentFragment()

    View Slide

  23. DocumentFragment is a “lightweight” or
    “minimal” Document object. It is very common
    to want to be able to extract a portion of a
    document’s tree or to create a new fragment of
    a document.
    Document Object Model (DOM) Level 1 Specification
    http://www.w3.org/TR/REC-DOM-Level-1/

    View Slide

  24. When a DocumentFragment is inserted into a
    Document…the children of the
    DocumentFragment and not the
    DocumentFragment itself are inserted into the
    Node.
    Document Object Model (DOM) Level 1 Specification
    http://www.w3.org/TR/REC-DOM-Level-1/

    View Slide







  25. Vivienne…
    Julia Dress

    $275
    rental


    $1739
    retail







    https://gist.github.com/mwunsch/29bca83eaf7649873900

    View Slide

  26. var
    el = document.getElementById("grid-thumb-viv9"),
    frag = document.createDocumentFragment(),
    walker = walkerFactory(document.body),
    fragWalker = walkerFactory(frag),
    diffs = [],
    diff;
    https://gist.github.com/mwunsch/29bca83eaf7649873900
    frag.appendChild(el.cloneNode(true));
    frag.querySelector(".thumb-price").textContent = "$285 rental";
    while (walker.nextNode() && fragWalker.nextNode()) {
    if (!walker.currentNode.isEqualNode(fragWalker.currentNode)) {
    diffs.push([walker.currentNode, fragWalker.currentNode]);
    }
    }

    View Slide

  27. do {
    diff = diffs.pop();
    if (diff[0].isEqualNode(diff[1])) break;
    if (diff[0].parentNode) {
    diff[0].parentNode.replaceChild(
    diff[1].cloneNode(true),
    diff[0]);
    }
    } while (diffs.length)
    https://gist.github.com/mwunsch/29bca83eaf7649873900

    View Slide

  28. do {
    diff = diffs.pop()
    if (diff[0].isEqualNode(diff[1])) break
    if (diff[0].parentNode) {
    diff[0].parentNode.replaceChild(
    diff[1].cloneNode(true)
    diff[0])
    }
    } while (diffs.length)
    https://gist.github.com/mwunsch/29bca83eaf7649873900
    CO
    NSIDERED
    HARM
    FUL

    View Slide

  29. FUNCTIONAL PEARL
    GÉRARD HUET
    INRIA Rocquencourt, France
    The Zipper

    View Slide

  30. HEADER
    HGROUP
    H2
    H1
    SECTION FOOTER
    DIV
    BODY

    View Slide

  31. HEADER
    HGROUP
    H1
    SECTION FOOTER
    DIV
    BODY
    H2

    View Slide

  32. HEADER
    HGROUP
    H1
    SECTION FOOTER
    DIV
    BODY
    H2

    View Slide

  33. var
    el = document.getElementById("grid-thumb-viv9"),
    loc = new Zipper(el);
    var designer = location
    .goDown()
    .goDown()
    .goRight()
    .goDown();
    https://gist.github.com/mwunsch/d46a4ebde8567e2e5102
    >> Zipper {
    tree: div.thumb-designer,
    crumb: Breadcrumb
    }

    View Slide

  34. $

    View Slide

  35. Further Reading
    • DOM Living Standard: https://dom.spec.whatwg.org/
    • Range: https://developer.mozilla.org/en-US/docs/Web/API/Range
    • HTMLBars: https://github.com/tildeio/htmlbars
    • [WIP] Implement Glimmer Engine: https://github.com/emberjs/
    ember.js/pull/10501
    • React Reconciliation: https://facebook.github.io/react/docs/
    reconciliation.html
    • Lee Byron, Immutable Data and React: https://youtu.be/I7IdS-PbEgI

    View Slide

  36. Dante and Virgil Penetrating the Forest
    William Blake, 1824–27

    View Slide

  37. ^D

    View Slide