| Index: Source/devtools/front_end/SuggestionBuilder.js
|
| diff --git a/Source/devtools/front_end/SuggestionBuilder.js b/Source/devtools/front_end/SuggestionBuilder.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7d4e41b36e81a2c43256af535d0e95371ed016a7
|
| --- /dev/null
|
| +++ b/Source/devtools/front_end/SuggestionBuilder.js
|
| @@ -0,0 +1,152 @@
|
| +/*
|
| + * Copyright (C) 2013 Google Inc. All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + */
|
| +
|
| +/**
|
| + * @constructor
|
| + * @implements {WebInspector.TextFilterUI.SuggestionBuilder}
|
| + * @param {!Array.<string>} keys
|
| + */
|
| +WebInspector.SuggestionBuilder = function(keys)
|
| +{
|
| + this._keys = keys;
|
| + this._valueSets = {};
|
| + this._valueLists = {};
|
| +}
|
| +
|
| +WebInspector.SuggestionBuilder.prototype = {
|
| + /**
|
| + * @param {!HTMLInputElement} input
|
| + * @return {?Array.<string>}
|
| + */
|
| + buildSuggestions: function(input)
|
| + {
|
| + var text = input.value;
|
| + var cursorPosition = input.selectionStart;
|
| + if (cursorPosition !== text.length)
|
| + return null;
|
| +
|
| + var prefix = text.substring(text.lastIndexOf(" ") + 1);
|
| + var valueDelimiterIndex = prefix.indexOf(":");
|
| +
|
| + var suggestions = [];
|
| + if (valueDelimiterIndex === -1) {
|
| + for (var j = 0; j < this._keys.length; ++j) {
|
| + if (this._keys[j].startsWith(prefix))
|
| + suggestions.push(this._keys[j] + ":");
|
| + }
|
| + } else {
|
| + var key = prefix.substring(0, valueDelimiterIndex);
|
| + var value = prefix.substring(valueDelimiterIndex + 1);
|
| + var items = this._values(key);
|
| + for (var i = 0; i < items.length; ++i) {
|
| + if (items[i].startsWith(value) && (items[i] !== value))
|
| + suggestions.push(key + ":" + items[i]);
|
| + }
|
| + }
|
| + return suggestions;
|
| + },
|
| +
|
| + /**
|
| + * @param {!HTMLInputElement} input
|
| + * @param {string} suggestion
|
| + */
|
| + applySuggestion: function(input, suggestion)
|
| + {
|
| + var text = input.value;
|
| + text = text.substring(0, text.lastIndexOf(" ") + 1) + suggestion;
|
| + input.value = text;
|
| + },
|
| +
|
| + /**
|
| + * @param {string} key
|
| + * @return {!Array.<string>}
|
| + */
|
| + _values: function(key)
|
| + {
|
| + var result = this._valueLists[key];
|
| + if (!result)
|
| + return [];
|
| +
|
| + result.sort();
|
| + return result;
|
| + },
|
| +
|
| + /**
|
| + * @param {string} key
|
| + * @param {?string=} value
|
| + */
|
| + addItem: function(key, value)
|
| + {
|
| + if (!value)
|
| + return;
|
| +
|
| + var set = this._valueSets[key];
|
| + var list = this._valueLists[key];
|
| + if (!set) {
|
| + set = {};
|
| + this._valueSets[key] = set;
|
| + list = [];
|
| + this._valueLists[key] = list;
|
| + }
|
| +
|
| + if (set[value])
|
| + return;
|
| +
|
| + set[value] = true;
|
| + list.push(value);
|
| + },
|
| +
|
| + /**
|
| + * @param {string} query
|
| + * @return {{textual: ?RegExp, specialized: !Object.<string, string>}}
|
| + */
|
| + parseQuery: function(query)
|
| + {
|
| + var specialized = {};
|
| + var parts = query.split(/\s+/);
|
| + var textualParts = [];
|
| + for (var i = 0; i < parts.length; ++i) {
|
| + var part = parts[i];
|
| + var colonIndex = part.indexOf(":");
|
| + if (colonIndex !== -1) {
|
| + var field = part.substr(0, colonIndex);
|
| + if (this._keys.indexOf(field) !== -1) {
|
| + var value = part.substr(colonIndex + 1);
|
| + specialized[field] = value;
|
| + continue;
|
| + }
|
| + }
|
| + if (part)
|
| + textualParts.push(part.escapeForRegExp());
|
| + }
|
| + var textual = textualParts.length ? new RegExp(textualParts.join("\\s*"), "i") : null;
|
| + return {textual: textual, specialized: specialized};
|
| + }
|
| +};
|
|
|