blob: 4599c0270b972453cf8c13bb9bbbe725c9b256e3 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Utilities for finding DOM nodes and CursorSelection's.
*/
goog.provide('cvox.FindUtil');
goog.require('cvox.BareObjectWalker');
goog.require('cvox.CursorSelection');
/**
* @type {!cvox.BareObjectWalker}
* @private
*/
cvox.FindUtil.objectWalker_ = new cvox.BareObjectWalker();
/**
* Finds the next selection that matches the predicate function starting from
* sel. Undefined if the nodes in sel are not attached to the document.
* @param {!cvox.CursorSelection} sel The selection from which to start.
* @param {function(Array<Node>):Node} predicate A function taking a
* unique ancestor tree and outputting Node if the ancestor tree matches
* the desired node to find.
* @param {boolean=} opt_initialNode Whether to start the search from node
* (true), or the next node (false); defaults to false.
* @return {cvox.CursorSelection} The selection that was found.
* null if end of document reached.
*/
cvox.FindUtil.findNext = function(sel, predicate, opt_initialNode) {
var r = sel.isReversed();
var cur =
new cvox.CursorSelection(sel.absStart(), sel.absStart()).setReversed(r);
// We may have been sync'ed into a subtree of the current predicate match.
// Find our ancestor that matches the predicate.
var ancestor;
if (ancestor = predicate(cvox.DomUtil.getAncestors(cur.start.node))) {
cur = cvox.CursorSelection.fromNode(ancestor).setReversed(r);
if (opt_initialNode) {
return cur;
}
}
while (cur) {
// Use ObjectWalker's traversal which guarantees us a stable iteration of
// the DOM including returning null at page bounds.
cur = cvox.FindUtil.objectWalker_.next(cur);
var retNode = null;
if (!cur ||
(retNode = predicate(cvox.DomUtil.getAncestors(cur.start.node)))) {
return retNode ? cvox.CursorSelection.fromNode(retNode) : null;
}
// Iframes require inter-frame messaging.
if (cur.start.node.tagName == 'IFRAME') {
return cur;
}
}
return null;
};