Home | History | Annotate | Download | only in common
      1 // Copyright 2014 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 /**
      6  * @fileoverview Utilities for finding DOM nodes and CursorSelection's.
      7  */
      8 
      9 
     10 goog.provide('cvox.FindUtil');
     11 
     12 goog.require('cvox.BareObjectWalker');
     13 goog.require('cvox.CursorSelection');
     14 
     15 
     16 /**
     17  * @type {!cvox.BareObjectWalker}
     18  * @private
     19  */
     20 cvox.FindUtil.objectWalker_ = new cvox.BareObjectWalker();
     21 
     22 
     23 /**
     24  * Finds the next selection that matches the predicate function starting from
     25  * sel. Undefined if the nodes in sel are not attached to the document.
     26  * @param {!cvox.CursorSelection} sel The selection from which to start.
     27  * @param {function(Array.<Node>):Node} predicate A function taking a
     28  * unique ancestor tree and outputting Node if the ancestor tree matches
     29  * the desired node to find.
     30  * @param {boolean=} opt_initialNode Whether to start the search from node
     31  * (true), or the next node (false); defaults to false.
     32  * @return {cvox.CursorSelection} The selection that was found.
     33  * null if end of document reached.
     34  */
     35 cvox.FindUtil.findNext = function(sel, predicate, opt_initialNode) {
     36   var r = sel.isReversed();
     37   var cur = new cvox.CursorSelection(sel.absStart(), sel.absStart())
     38       .setReversed(r);
     39 
     40   // We may have been sync'ed into a subtree of the current predicate match.
     41   // Find our ancestor that matches the predicate.
     42   var ancestor;
     43   if (ancestor = predicate(cvox.DomUtil.getAncestors(cur.start.node))) {
     44     cur = cvox.CursorSelection.fromNode(ancestor).setReversed(r);
     45     if (opt_initialNode) {
     46       return cur;
     47     }
     48   }
     49 
     50   while (cur) {
     51     // Use ObjectWalker's traversal which guarantees us a stable iteration of
     52     // the DOM including returning null at page bounds.
     53     cur = cvox.FindUtil.objectWalker_.next(cur);
     54     var retNode = null;
     55     if (!cur ||
     56         (retNode = predicate(cvox.DomUtil.getAncestors(cur.start.node)))) {
     57       return retNode ? cvox.CursorSelection.fromNode(retNode) : null;
     58     }
     59 
     60     // Iframes require inter-frame messaging.
     61     if (cur.start.node.tagName == 'IFRAME') {
     62       return cur;
     63     }
     64   }
     65   return null;
     66 };
     67