1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 function watchForTag(tagName, cb) { 6 if (!document.body) 7 return; 8 9 function findChildTags(queryNode) { 10 $Array.forEach(queryNode.querySelectorAll(tagName), function(node) { 11 cb(node); 12 }); 13 } 14 // Query tags already in the document. 15 findChildTags(document.body); 16 17 // Observe the tags added later. 18 var documentObserver = new MutationObserver(function(mutations) { 19 $Array.forEach(mutations, function(mutation) { 20 $Array.forEach(mutation.addedNodes, function(addedNode) { 21 if (addedNode.nodeType == Node.ELEMENT_NODE) { 22 if (addedNode.tagName == tagName) 23 cb(addedNode); 24 findChildTags(addedNode); 25 } 26 }); 27 }); 28 }); 29 documentObserver.observe(document, {subtree: true, childList: true}); 30 } 31 32 // Expose a function to watch the |tagName| introduction via mutation observer. 33 // 34 // We employee mutation observer to watch on any introduction of |tagName| 35 // within document so that we may handle it accordingly (either creating it or 36 // reporting error due to lack of permission). 37 // Think carefully about when to call this. On one hand, mutation observer 38 // functions on document, so we need to make sure document is finished 39 // parsing. To satisfy this, document.readyState has to be "interactive" or 40 // after. On the other hand, we intend to do this as early as possible so that 41 // developer would have no chance to bring in any conflicted property. To meet 42 // this requirement, we choose "readystatechange" event of window and use 43 // capturing way. 44 function addTagWatcher(tagName, cb) { 45 var useCapture = true; 46 window.addEventListener('readystatechange', function listener(event) { 47 if (document.readyState == 'loading') 48 return; 49 50 watchForTag(tagName, cb); 51 window.removeEventListener(event.type, listener, useCapture); 52 }, useCapture); 53 } 54 55 exports.addTagWatcher = addTagWatcher; 56