Path: blob/trunk/third_party/closure/goog/dom/pattern/repeat.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 a tag and all of its children.16*17* @author [email protected] (Robby Walker)18*/1920goog.provide('goog.dom.pattern.Repeat');2122goog.require('goog.dom.NodeType');23goog.require('goog.dom.pattern.AbstractPattern');24goog.require('goog.dom.pattern.MatchType');25262728/**29* Pattern object that matches a repetition of another pattern.30* @param {goog.dom.pattern.AbstractPattern} pattern The pattern to31* repetitively match.32* @param {number=} opt_minimum The minimum number of times to match. Defaults33* to 0.34* @param {number=} opt_maximum The maximum number of times to match. Defaults35* to unlimited.36* @constructor37* @extends {goog.dom.pattern.AbstractPattern}38* @final39*/40goog.dom.pattern.Repeat = function(pattern, opt_minimum, opt_maximum) {41/**42* Pattern to repetitively match.43*44* @private {goog.dom.pattern.AbstractPattern}45*/46this.pattern_ = pattern;4748/**49* Minimum number of times to match the pattern.50*51* @private {number}52*/53this.minimum_ = opt_minimum || 0;5455/**56* Optional maximum number of times to match the pattern. A {@code null} value57* will be treated as infinity.58*59* @private {?number}60*/61this.maximum_ = opt_maximum || null;6263/**64* The matched nodes.65*66* @type {Array<Node>}67*/68this.matches = [];6970/**71* Number of times the pattern has matched.72*73* @type {number}74*/75this.count = 0;7677/**78* Whether the pattern has recently matched or failed to match and will need79* to be reset when starting a new round of matches.80*81* @private {boolean}82*/83this.needsReset_ = false;84};85goog.inherits(goog.dom.pattern.Repeat, goog.dom.pattern.AbstractPattern);868788/**89* Test whether the given token continues a repeated series of matches of the90* pattern given in the constructor.91*92* @param {Node} token Token to match against.93* @param {goog.dom.TagWalkType} type The type of token.94* @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern95* matches, <code>BACKTRACK_MATCH</code> if the pattern does not match96* but already had accumulated matches, <code>MATCHING</code> if the pattern97* starts a match, and <code>NO_MATCH</code> if the pattern does not match.98* @suppress {missingProperties} See the broken line below.99* @override100*/101goog.dom.pattern.Repeat.prototype.matchToken = function(token, type) {102// Reset if we're starting a new match103if (this.needsReset_) {104this.reset();105}106107// If the option is set, ignore any whitespace only text nodes108if (token.nodeType == goog.dom.NodeType.TEXT &&109token.nodeValue.match(/^\s+$/)) {110return goog.dom.pattern.MatchType.MATCHING;111}112113switch (this.pattern_.matchToken(token, type)) {114case goog.dom.pattern.MatchType.MATCH:115// Record the first token we match.116if (this.count == 0) {117this.matchedNode = token;118}119120// Mark the match121this.count++;122123// Add to the list124this.matches.push(this.pattern_.matchedNode);125126// Check if this match hits our maximum127if (this.maximum_ !== null && this.count == this.maximum_) {128this.needsReset_ = true;129return goog.dom.pattern.MatchType.MATCH;130} else {131return goog.dom.pattern.MatchType.MATCHING;132}133134case goog.dom.pattern.MatchType.MATCHING:135// This can happen when our child pattern is a sequence or a repetition.136return goog.dom.pattern.MatchType.MATCHING;137138case goog.dom.pattern.MatchType.BACKTRACK_MATCH:139// This happens if our child pattern is repetitive too.140// TODO(robbyw): Backtrack further if necessary.141this.count++;142143// NOTE(nicksantos): This line of code is broken. this.patterns_ doesn't144// exist, and this.currentPosition_ doesn't exist. When this is fixed,145// remove the missingProperties suppression above.146if (this.currentPosition_ == this.patterns_.length) {147this.needsReset_ = true;148return goog.dom.pattern.MatchType.BACKTRACK_MATCH;149} else {150// Retry the same token on the next iteration of the child pattern.151return this.matchToken(token, type);152}153154default:155this.needsReset_ = true;156if (this.count >= this.minimum_) {157return goog.dom.pattern.MatchType.BACKTRACK_MATCH;158} else {159return goog.dom.pattern.MatchType.NO_MATCH;160}161}162};163164165/**166* Reset any internal state this pattern keeps.167* @override168*/169goog.dom.pattern.Repeat.prototype.reset = function() {170this.pattern_.reset();171this.count = 0;172this.needsReset_ = false;173this.matches.length = 0;174};175176177