Path: blob/trunk/third_party/closure/goog/dom/pattern/childmatches.js
2868 views
// Copyright 2007 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview DOM pattern to match any children of a tag, and16* specifically collect those that match a child pattern.17*18* @author [email protected] (Robby Walker)19*/2021goog.provide('goog.dom.pattern.ChildMatches');2223goog.require('goog.dom.pattern.AllChildren');24goog.require('goog.dom.pattern.MatchType');25262728/**29* Pattern object that matches any nodes at or below the current tree depth.30*31* @param {goog.dom.pattern.AbstractPattern} childPattern Pattern to collect32* child matches of.33* @param {number=} opt_minimumMatches Enforce a minimum nuber of matches.34* Defaults to 0.35* @constructor36* @extends {goog.dom.pattern.AllChildren}37* @final38*/39goog.dom.pattern.ChildMatches = function(childPattern, opt_minimumMatches) {40/**41* The child pattern to collect matches from.42*43* @private {goog.dom.pattern.AbstractPattern}44*/45this.childPattern_ = childPattern;4647/**48* Array of matched child nodes.49*50* @type {Array<Node>}51*/52this.matches = [];5354/**55* Minimum number of matches.56*57* @private {number}58*/59this.minimumMatches_ = opt_minimumMatches || 0;6061/**62* Whether the pattern has recently matched or failed to match and will need63* to be reset when starting a new round of matches.64*65* @private {boolean}66*/67this.needsReset_ = false;6869goog.dom.pattern.ChildMatches.base(this, 'constructor');70};71goog.inherits(goog.dom.pattern.ChildMatches, goog.dom.pattern.AllChildren);727374/**75* Test whether the given token is on the same level.76*77* @param {Node} token Token to match against.78* @param {goog.dom.TagWalkType} type The type of token.79* @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the80* same level or deeper and {@code BACKTRACK_MATCH} if not.81* @override82*/83goog.dom.pattern.ChildMatches.prototype.matchToken = function(token, type) {84// Defer resets so we maintain our matches array until the last possible time.85if (this.needsReset_) {86this.reset();87}8889// Call the super-method to ensure we stay in the child tree.90var status =91goog.dom.pattern.AllChildren.prototype.matchToken.apply(this, arguments);9293switch (status) {94case goog.dom.pattern.MatchType.MATCHING:95var backtrack = false;9697switch (this.childPattern_.matchToken(token, type)) {98case goog.dom.pattern.MatchType.BACKTRACK_MATCH:99backtrack = true;100case goog.dom.pattern.MatchType.MATCH:101// Collect the match.102this.matches.push(this.childPattern_.matchedNode);103break;104105default:106// Keep trying if we haven't hit a terminal state.107break;108}109110if (backtrack) {111// The only interesting result is a MATCH, since BACKTRACK_MATCH means112// we are hitting an infinite loop on something like a Repeat(0).113if (this.childPattern_.matchToken(token, type) ==114goog.dom.pattern.MatchType.MATCH) {115this.matches.push(this.childPattern_.matchedNode);116}117}118return goog.dom.pattern.MatchType.MATCHING;119120case goog.dom.pattern.MatchType.BACKTRACK_MATCH:121// TODO(robbyw): this should return something like BACKTRACK_NO_MATCH122// when we don't meet our minimum.123this.needsReset_ = true;124return (this.matches.length >= this.minimumMatches_) ?125goog.dom.pattern.MatchType.BACKTRACK_MATCH :126goog.dom.pattern.MatchType.NO_MATCH;127128default:129this.needsReset_ = true;130return status;131}132};133134135/**136* Reset any internal state this pattern keeps.137* @override138*/139goog.dom.pattern.ChildMatches.prototype.reset = function() {140this.needsReset_ = false;141this.matches.length = 0;142this.childPattern_.reset();143goog.dom.pattern.AllChildren.prototype.reset.call(this);144};145146147