Modules (181)

DocumentObserver

Description

Dependencies

This module has no dependencies

Variables

CSS

CSS related commands and notifications

    var CSS = {

Utils

Common functions.

    var Utils = {

        isExternalStylesheet: function (node) {
            return (node.nodeName.toUpperCase() === "LINK" && node.rel === "stylesheet" && node.href);
        },
        isExternalScript: function (node) {
            return (node.nodeName.toUpperCase() === "SCRIPT" && node.src);
        }
    };

Functions

Private

_onNodesAdded

process related docs added

    function _onNodesAdded(nodes) {
        var i;
        for (i = 0; i < nodes.length; i++) {
            //check for Javascript files
            if (Utils.isExternalScript(nodes[i])) {
                _transport.send(JSON.stringify({
                    method: 'ScriptAdded',
                    src: nodes[i].src
                }));
            }
            //check for stylesheets
            if (Utils.isExternalStylesheet(nodes[i])) {
                CSS.checkForStylesheetLoaded(nodes[i].href);
            }
        }
    }
Private

_onNodesRemoved

process related docs removed

    function _onNodesRemoved(nodes) {
        var i;
        //iterate on removed nodes
        for (i = 0; i < nodes.length; i++) {

            // check for external JS files
            if (Utils.isExternalScript(nodes[i])) {
                _transport.send(JSON.stringify({
                    method: 'ScriptRemoved',
                    src: nodes[i].src
                }));
            }
            //check for external StyleSheets
            if (Utils.isExternalStylesheet(nodes[i])) {
                CSS.notifyStylesheetRemoved(nodes[i].href);
            }
        }
    }

    function _enableListeners() {
        // enable MutationOberver if it's supported
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
        if (MutationObserver) {
            var observer = new MutationObserver(function (mutations) {
                mutations.forEach(function (mutation) {
                    if (mutation.addedNodes.length > 0) {
                        _onNodesAdded(mutation.addedNodes);
                    }
                    if (mutation.removedNodes.length > 0) {
                        _onNodesRemoved(mutation.removedNodes);
                    }
                });
            });
            observer.observe(_document, {
                childList: true,
                subtree: true
            });
        } else {
            // use MutationEvents as fallback
            window.document.addEventListener('DOMNodeInserted', function niLstnr(e) {
                _onNodesAdded([e.target]);
            });
            window.document.addEventListener('DOMNodeRemoved', function nrLstnr(e) {
                _onNodesRemoved([e.target]);
            });
        }
    }

related

Retrieves related documents (external CSS and JS files)

Returns: {scripts: object,stylesheets: object}
Related scripts and stylesheets
    function related() {

        var rel = {
            scripts: {},
            stylesheets: {}
        };
        var i;
        // iterate on document scripts (HTMLCollection doesn't provide forEach iterator).
        for (i = 0; i < _document.scripts.length; i++) {
            // add only external scripts
            if (_document.scripts[i].src) {
                rel.scripts[_document.scripts[i].src] = true;
            }
        }

        var s, j;
        //traverse @import rules
        var traverseRules = function _traverseRules(sheet, base) {
            var i,
                href = sheet.href,
                cssRules;

            // Deal with Firefox's SecurityError when accessing sheets
            // from other domains. Chrome will safely return `undefined`.
            try {
                cssRules = sheet.cssRules;
            } catch (e) {
                if (e.name !== "SecurityError") {
                    throw e;
                }
            }

            if (href && cssRules) {
                if (rel.stylesheets[href] === undefined) {
                    rel.stylesheets[href] = [];
                }
                rel.stylesheets[href].push(base);

                for (i = 0; i < cssRules.length; i++) {
                    if (cssRules[i].href) {
                        traverseRules(cssRules[i].styleSheet, base);
                    }
                }
            }
        };
        //iterate on document.stylesheets (StyleSheetList doesn't provide forEach iterator).
        for (j = 0; j < window.document.styleSheets.length; j++) {
            s = window.document.styleSheets[j];
            traverseRules(s, s.href);
        }
        return rel;
    }

start

Start listening for events and send initial related documents message.

document HTMLDocument
transport object
Live development transport connection
    function start(document, transport) {
        _transport = transport;
        _document = document;
        // start listening to node changes
        _enableListeners();

        var rel = related();

        // send the current status of related docs.
        _transport.send(JSON.stringify({
            method: "DocumentRelated",
            related: rel
        }));
        // initialize stylesheets with current status for further notifications.
        CSS.stylesheets = rel.stylesheets;
    }

stop

Stop listening. TODO currently a no-op.

    function stop() {

    }

    var DocumentObserver = {
        start: start,
        stop: stop,
        related: related
    };

    ProtocolManager.setDocumentObserver(DocumentObserver);

}(this));