Home | History | Annotate | Download | only in extensions
      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