A Pen by Harris Novick on CodePen.
Created
October 3, 2013 16:46
-
-
Save Saminou24/6813009 to your computer and use it in GitHub Desktop.
A Pen by Harris Novick.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!-- | |
| Copyright (C) 2006, 2007, 2008 Apple 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: | |
| 1. Redistributions of source code must retain the above copyright | |
| notice, this list of conditions and the following disclaimer. | |
| 2. 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. | |
| 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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. | |
| --> | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="content-type" content="text/html; charset=utf-8"> | |
| <link rel="stylesheet" type="text/css" href="devTools.css"> | |
| <script type="text/javascript" src="DevTools.js"></script> | |
| </head> | |
| <body class="detached" id="webkit-web-inspector"> | |
| <div class="outer"> | |
| <div id="toolbar"> | |
| <div class="toolbar-item close-left"><button id="close-button-left"></button></div> | |
| <div id="toolbar-controls"> | |
| <div class="toolbar-item"><button id="toolbar-dropdown-arrow" class="toolbar-label">»</button></div> | |
| <div class="toolbar-item close-right"><button id="close-button-right"></button></div> | |
| </div> | |
| </div> | |
| <div id="main"> | |
| <div id="floating-status-bar-container" class="status-bar"><div id="floating-status-bar-resizer"></div></div> | |
| </div> | |
| <div id="drawer"></div> | |
| <div id="main-status-bar" class="status-bar"> | |
| <div id="bottom-status-bar-container"> | |
| <div id="panel-status-bar"></div> | |
| </div> | |
| <div id="error-warning-count" class="hidden"></div> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file has been truncated, but you can view the full file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Object.isEmpty = function(obj) | |
| { | |
| for (var i in obj) | |
| return false; | |
| return true; | |
| } | |
| Object.values = function(obj) | |
| { | |
| var keys = Object.keys(obj); | |
| var result = []; | |
| for (var i = 0; i < keys.length; ++i) | |
| result.push(obj[keys[i]]); | |
| return result; | |
| } | |
| String.prototype.hasSubstring = function(string, caseInsensitive) | |
| { | |
| if (!caseInsensitive) | |
| return this.indexOf(string) !== -1; | |
| return this.match(new RegExp(string.escapeForRegExp(), "i")); | |
| } | |
| String.prototype.findAll = function(string) | |
| { | |
| var matches = []; | |
| var i = this.indexOf(string); | |
| while (i !== -1) { | |
| matches.push(i); | |
| i = this.indexOf(string, i + string.length); | |
| } | |
| return matches; | |
| } | |
| String.prototype.lineEndings = function() | |
| { | |
| if (!this._lineEndings) { | |
| this._lineEndings = this.findAll("\n"); | |
| this._lineEndings.push(this.length); | |
| } | |
| return this._lineEndings; | |
| } | |
| String.prototype.escapeCharacters = function(chars) | |
| { | |
| var foundChar = false; | |
| for (var i = 0; i < chars.length; ++i) { | |
| if (this.indexOf(chars.charAt(i)) !== -1) { | |
| foundChar = true; | |
| break; | |
| } | |
| } | |
| if (!foundChar) | |
| return this; | |
| var result = ""; | |
| for (var i = 0; i < this.length; ++i) { | |
| if (chars.indexOf(this.charAt(i)) !== -1) | |
| result += "\\"; | |
| result += this.charAt(i); | |
| } | |
| return result; | |
| } | |
| String.prototype.escapeForRegExp = function() | |
| { | |
| return this.escapeCharacters("^[]{}()\\.$*+?|"); | |
| } | |
| String.prototype.escapeHTML = function() | |
| { | |
| return this.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); | |
| } | |
| String.prototype.collapseWhitespace = function() | |
| { | |
| return this.replace(/[\s\xA0]+/g, " "); | |
| } | |
| String.prototype.trimMiddle = function(maxLength) | |
| { | |
| if (this.length <= maxLength) | |
| return this; | |
| var leftHalf = maxLength >> 1; | |
| var rightHalf = maxLength - leftHalf - 1; | |
| return this.substr(0, leftHalf) + "\u2026" + this.substr(this.length - rightHalf, rightHalf); | |
| } | |
| String.prototype.trimEnd = function(maxLength) | |
| { | |
| if (this.length <= maxLength) | |
| return this; | |
| return this.substr(0, maxLength - 1) + "\u2026"; | |
| } | |
| String.prototype.trimURL = function(baseURLDomain) | |
| { | |
| var result = this.replace(/^(https|http|file):\/\//i, ""); | |
| if (baseURLDomain) | |
| result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), ""); | |
| return result; | |
| } | |
| function sanitizeHref(href) | |
| { | |
| return href && href.trim().toLowerCase().startsWith("javascript:") ? "" : href; | |
| } | |
| String.prototype.removeURLFragment = function() | |
| { | |
| var fragmentIndex = this.indexOf("#"); | |
| if (fragmentIndex == -1) | |
| fragmentIndex = this.length; | |
| return this.substring(0, fragmentIndex); | |
| } | |
| String.prototype.startsWith = function(substring) | |
| { | |
| return !this.lastIndexOf(substring, 0); | |
| } | |
| String.prototype.endsWith = function(substring) | |
| { | |
| return this.indexOf(substring, this.length - substring.length) !== -1; | |
| } | |
| Number.constrain = function(num, min, max) | |
| { | |
| if (num < min) | |
| num = min; | |
| else if (num > max) | |
| num = max; | |
| return num; | |
| } | |
| Date.prototype.toISO8601Compact = function() | |
| { | |
| function leadZero(x) | |
| { | |
| return x > 9 ? '' + x : '0' + x | |
| } | |
| return this.getFullYear() + | |
| leadZero(this.getMonth() + 1) + | |
| leadZero(this.getDate()) + 'T' + | |
| leadZero(this.getHours()) + | |
| leadZero(this.getMinutes()) + | |
| leadZero(this.getSeconds()); | |
| } | |
| Object.defineProperty(Array.prototype, "remove", | |
| { | |
| value: function(value, onlyFirst) | |
| { | |
| if (onlyFirst) { | |
| var index = this.indexOf(value); | |
| if (index !== -1) | |
| this.splice(index, 1); | |
| return; | |
| } | |
| var length = this.length; | |
| for (var i = 0; i < length; ++i) { | |
| if (this[i] === value) | |
| this.splice(i, 1); | |
| } | |
| } | |
| }); | |
| Object.defineProperty(Array.prototype, "keySet", | |
| { | |
| value: function() | |
| { | |
| var keys = {}; | |
| for (var i = 0; i < this.length; ++i) | |
| keys[this[i]] = true; | |
| return keys; | |
| } | |
| }); | |
| Object.defineProperty(Array.prototype, "upperBound", | |
| { | |
| value: function(value) | |
| { | |
| var first = 0; | |
| var count = this.length; | |
| while (count > 0) { | |
| var step = count >> 1; | |
| var middle = first + step; | |
| if (value >= this[middle]) { | |
| first = middle + 1; | |
| count -= step + 1; | |
| } else | |
| count = step; | |
| } | |
| return first; | |
| } | |
| }); | |
| Object.defineProperty(Array.prototype, "rotate", | |
| { | |
| value: function(index) | |
| { | |
| var result = []; | |
| for (var i = index; i < index + this.length; ++i) | |
| result.push(this[i % this.length]); | |
| return result; | |
| } | |
| }); | |
| Object.defineProperty(Uint32Array.prototype, "sort", { | |
| value: Array.prototype.sort | |
| }); | |
| (function() { | |
| var partition = { | |
| value: function(comparator, left, right, pivotIndex) | |
| { | |
| function swap(array, i1, i2) | |
| { | |
| var temp = array[i1]; | |
| array[i1] = array[i2]; | |
| array[i2] = temp; | |
| } | |
| var pivotValue = this[pivotIndex]; | |
| swap(this, right, pivotIndex); | |
| var storeIndex = left; | |
| for (var i = left; i < right; ++i) { | |
| if (comparator(this[i], pivotValue) < 0) { | |
| swap(this, storeIndex, i); | |
| ++storeIndex; | |
| } | |
| } | |
| swap(this, right, storeIndex); | |
| return storeIndex; | |
| } | |
| }; | |
| Object.defineProperty(Array.prototype, "partition", partition); | |
| Object.defineProperty(Uint32Array.prototype, "partition", partition); | |
| var sortRange = { | |
| value: function(comparator, leftBound, rightBound, k) | |
| { | |
| function quickSortFirstK(array, comparator, left, right, k) | |
| { | |
| if (right <= left) | |
| return; | |
| var pivotIndex = Math.floor(Math.random() * (right - left)) + left; | |
| var pivotNewIndex = array.partition(comparator, left, right, pivotIndex); | |
| quickSortFirstK(array, comparator, left, pivotNewIndex - 1, k); | |
| if (pivotNewIndex < left + k - 1) | |
| quickSortFirstK(array, comparator, pivotNewIndex + 1, right, k); | |
| } | |
| if (leftBound === 0 && rightBound === (this.length - 1) && k === this.length) | |
| this.sort(comparator); | |
| else | |
| quickSortFirstK(this, comparator, leftBound, rightBound, k); | |
| return this; | |
| } | |
| } | |
| Object.defineProperty(Array.prototype, "sortRange", sortRange); | |
| Object.defineProperty(Uint32Array.prototype, "sortRange", sortRange); | |
| })(); | |
| Object.defineProperty(Array.prototype, "qselect", | |
| { | |
| value: function(k, comparator) | |
| { | |
| if (k < 0 || k >= this.length) | |
| return; | |
| if (!comparator) | |
| comparator = function(a, b) { return a - b; } | |
| var low = 0; | |
| var high = this.length - 1; | |
| for (;;) { | |
| var pivotPosition = this.partition(comparator, low, high, Math.floor((high + low) / 2)); | |
| if (pivotPosition === k) | |
| return this[k]; | |
| else if (pivotPosition > k) | |
| high = pivotPosition - 1; | |
| else | |
| low = pivotPosition + 1; | |
| } | |
| } | |
| }); | |
| function binarySearch(object, array, comparator) | |
| { | |
| var first = 0; | |
| var last = array.length - 1; | |
| while (first <= last) { | |
| var mid = (first + last) >> 1; | |
| var c = comparator(object, array[mid]); | |
| if (c > 0) | |
| first = mid + 1; | |
| else if (c < 0) | |
| last = mid - 1; | |
| else | |
| return mid; | |
| } | |
| return -(first + 1); | |
| } | |
| Object.defineProperty(Array.prototype, "binaryIndexOf", | |
| { | |
| value: function(value, comparator) | |
| { | |
| var result = binarySearch(value, this, comparator); | |
| return result >= 0 ? result : -1; | |
| } | |
| }); | |
| Object.defineProperty(Array.prototype, "select", | |
| { | |
| value: function(field) | |
| { | |
| var result = new Array(this.length); | |
| for (var i = 0; i < this.length; ++i) | |
| result[i] = this[i][field]; | |
| return result; | |
| } | |
| }); | |
| function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction) | |
| { | |
| var index = binarySearch(anObject, aList, aFunction); | |
| if (index < 0) | |
| return -index - 1; | |
| else { | |
| while (index > 0 && aFunction(anObject, aList[index - 1]) === 0) | |
| index--; | |
| return index; | |
| } | |
| } | |
| Array.convert = function(list) | |
| { | |
| return Array.prototype.slice.call(list); | |
| } | |
| String.sprintf = function(format, var_arg) | |
| { | |
| return String.vsprintf(format, Array.prototype.slice.call(arguments, 1)); | |
| } | |
| String.tokenizeFormatString = function(format, formatters) | |
| { | |
| var tokens = []; | |
| var substitutionIndex = 0; | |
| function addStringToken(str) | |
| { | |
| tokens.push({ type: "string", value: str }); | |
| } | |
| function addSpecifierToken(specifier, precision, substitutionIndex) | |
| { | |
| tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex }); | |
| } | |
| function isDigit(c) | |
| { | |
| return !!/[0-9]/.exec(c); | |
| } | |
| var index = 0; | |
| for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) { | |
| addStringToken(format.substring(index, precentIndex)); | |
| index = precentIndex + 1; | |
| if (isDigit(format[index])) { | |
| var number = parseInt(format.substring(index), 10); | |
| while (isDigit(format[index])) | |
| ++index; | |
| if (number > 0 && format[index] === "$") { | |
| substitutionIndex = (number - 1); | |
| ++index; | |
| } | |
| } | |
| var precision = -1; | |
| if (format[index] === ".") { | |
| ++index; | |
| precision = parseInt(format.substring(index), 10); | |
| if (isNaN(precision)) | |
| precision = 0; | |
| while (isDigit(format[index])) | |
| ++index; | |
| } | |
| if (!(format[index] in formatters)) { | |
| addStringToken(format.substring(precentIndex, index + 1)); | |
| ++index; | |
| continue; | |
| } | |
| addSpecifierToken(format[index], precision, substitutionIndex); | |
| ++substitutionIndex; | |
| ++index; | |
| } | |
| addStringToken(format.substring(index)); | |
| return tokens; | |
| } | |
| String.standardFormatters = { | |
| d: function(substitution) | |
| { | |
| return !isNaN(substitution) ? substitution : 0; | |
| }, | |
| f: function(substitution, token) | |
| { | |
| if (substitution && token.precision > -1) | |
| substitution = substitution.toFixed(token.precision); | |
| return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0); | |
| }, | |
| s: function(substitution) | |
| { | |
| return substitution; | |
| } | |
| } | |
| String.vsprintf = function(format, substitutions) | |
| { | |
| return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult; | |
| } | |
| String.format = function(format, substitutions, formatters, initialValue, append) | |
| { | |
| if (!format || !substitutions || !substitutions.length) | |
| return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions }; | |
| function prettyFunctionName() | |
| { | |
| return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")"; | |
| } | |
| function warn(msg) | |
| { | |
| console.warn(prettyFunctionName() + ": " + msg); | |
| } | |
| function error(msg) | |
| { | |
| console.error(prettyFunctionName() + ": " + msg); | |
| } | |
| var result = initialValue; | |
| var tokens = String.tokenizeFormatString(format, formatters); | |
| var usedSubstitutionIndexes = {}; | |
| for (var i = 0; i < tokens.length; ++i) { | |
| var token = tokens[i]; | |
| if (token.type === "string") { | |
| result = append(result, token.value); | |
| continue; | |
| } | |
| if (token.type !== "specifier") { | |
| error("Unknown token type \"" + token.type + "\" found."); | |
| continue; | |
| } | |
| if (token.substitutionIndex >= substitutions.length) { | |
| error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped."); | |
| result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier); | |
| continue; | |
| } | |
| usedSubstitutionIndexes[token.substitutionIndex] = true; | |
| if (!(token.specifier in formatters)) { | |
| warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string."); | |
| result = append(result, substitutions[token.substitutionIndex]); | |
| continue; | |
| } | |
| result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token)); | |
| } | |
| var unusedSubstitutions = []; | |
| for (var i = 0; i < substitutions.length; ++i) { | |
| if (i in usedSubstitutionIndexes) | |
| continue; | |
| unusedSubstitutions.push(substitutions[i]); | |
| } | |
| return { formattedResult: result, unusedSubstitutions: unusedSubstitutions }; | |
| } | |
| function createSearchRegex(query, caseSensitive, isRegex) | |
| { | |
| var regexFlags = caseSensitive ? "g" : "gi"; | |
| var regexObject; | |
| if (isRegex) { | |
| try { | |
| regexObject = new RegExp(query, regexFlags); | |
| } catch (e) { | |
| } | |
| } | |
| if (!regexObject) | |
| regexObject = createPlainTextSearchRegex(query, regexFlags); | |
| return regexObject; | |
| } | |
| function createPlainTextSearchRegex(query, flags) | |
| { | |
| var regexSpecialCharacters = "[](){}+-*.,?\\^$|"; | |
| var regex = ""; | |
| for (var i = 0; i < query.length; ++i) { | |
| var c = query.charAt(i); | |
| if (regexSpecialCharacters.indexOf(c) != -1) | |
| regex += "\\"; | |
| regex += c; | |
| } | |
| return new RegExp(regex, flags || ""); | |
| } | |
| function countRegexMatches(regex, content) | |
| { | |
| var text = content; | |
| var result = 0; | |
| var match; | |
| while (text && (match = regex.exec(text))) { | |
| if (match[0].length > 0) | |
| ++result; | |
| text = text.substring(match.index + 1); | |
| } | |
| return result; | |
| } | |
| function numberToStringWithSpacesPadding(value, symbolsCount) | |
| { | |
| var numberString = value.toString(); | |
| var paddingLength = Math.max(0, symbolsCount - numberString.length); | |
| var paddingString = Array(paddingLength + 1).join("\u00a0"); | |
| return paddingString + numberString; | |
| } | |
| var Map = function() | |
| { | |
| this._map = {}; | |
| this._size = 0; | |
| } | |
| Map._lastObjectIdentifier = 0; | |
| Map.prototype = { | |
| put: function(key, value) | |
| { | |
| var objectIdentifier = key.__identifier; | |
| if (!objectIdentifier) { | |
| objectIdentifier = ++Map._lastObjectIdentifier; | |
| key.__identifier = objectIdentifier; | |
| } | |
| if (!this._map[objectIdentifier]) | |
| ++this._size; | |
| this._map[objectIdentifier] = [key, value]; | |
| }, | |
| remove: function(key) | |
| { | |
| var result = this._map[key.__identifier]; | |
| delete this._map[key.__identifier]; | |
| --this._size; | |
| return result ? result[1] : undefined; | |
| }, | |
| keys: function() | |
| { | |
| return this._list(0); | |
| }, | |
| values: function() | |
| { | |
| return this._list(1); | |
| }, | |
| _list: function(index) | |
| { | |
| var result = new Array(this._size); | |
| var i = 0; | |
| for (var objectIdentifier in this._map) | |
| result[i++] = this._map[objectIdentifier][index]; | |
| return result; | |
| }, | |
| get: function(key) | |
| { | |
| var entry = this._map[key.__identifier]; | |
| return entry ? entry[1] : undefined; | |
| }, | |
| size: function() | |
| { | |
| return this._size; | |
| }, | |
| clear: function() | |
| { | |
| this._map = {}; | |
| this._size = 0; | |
| } | |
| } | |
| function loadXHR(url, async, callback) | |
| { | |
| function onReadyStateChanged() | |
| { | |
| if (xhr.readyState !== XMLHttpRequest.DONE) | |
| return; | |
| if (xhr.status === 200) { | |
| callback(xhr.responseText); | |
| return; | |
| } | |
| callback(null); | |
| } | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("GET", url, async); | |
| if (async) | |
| xhr.onreadystatechange = onReadyStateChanged; | |
| xhr.send(null); | |
| if (!async) { | |
| if (xhr.status === 200) | |
| return xhr.responseText; | |
| return null; | |
| } | |
| return null; | |
| } | |
| function StringPool() | |
| { | |
| this.reset(); | |
| } | |
| StringPool.prototype = { | |
| intern: function(string) | |
| { | |
| if (string === "__proto__") | |
| return "__proto__"; | |
| var result = this._strings[string]; | |
| if (result === undefined) { | |
| this._strings[string] = string; | |
| result = string; | |
| } | |
| return result; | |
| }, | |
| reset: function() | |
| { | |
| this._strings = Object.create(null); | |
| }, | |
| internObjectStrings: function(obj, depthLimit) | |
| { | |
| if (typeof depthLimit !== "number") | |
| depthLimit = 100; | |
| else if (--depthLimit < 0) | |
| throw "recursion depth limit reached in StringPool.deepIntern(), perhaps attempting to traverse cyclical references?"; | |
| for (var field in obj) { | |
| switch (typeof obj[field]) { | |
| case "string": | |
| obj[field] = this.intern(obj[field]); | |
| break; | |
| case "object": | |
| this.internObjectStrings(obj[field], depthLimit); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| var _importedScripts = {}; | |
| function importScript(scriptName) | |
| { | |
| if (_importedScripts[scriptName]) | |
| return; | |
| _importedScripts[scriptName] = true; | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("GET", scriptName, false); | |
| xhr.send(null); | |
| window.eval(xhr.responseText + "\n//@ sourceURL=" + scriptName); | |
| } | |
| __whitespace = {" ":true, "\t":true, "\n":true, "\f":true, "\r":true}; | |
| difflib = { | |
| defaultJunkFunction: function (c) { | |
| return __whitespace.hasOwnProperty(c); | |
| }, | |
| stripLinebreaks: function (str) { return str.replace(/^[\n\r]*|[\n\r]*$/g, ""); }, | |
| stringAsLines: function (str) { | |
| var lfpos = str.indexOf("\n"); | |
| var crpos = str.indexOf("\r"); | |
| var linebreak = ((lfpos > -1 && crpos > -1) || crpos < 0) ? "\n" : "\r"; | |
| var lines = str.split(linebreak); | |
| for (var i = 0; i < lines.length; i++) { | |
| lines[i] = difflib.stripLinebreaks(lines[i]); | |
| } | |
| return lines; | |
| }, | |
| __reduce: function (func, list, initial) { | |
| if (initial != null) { | |
| var value = initial; | |
| var idx = 0; | |
| } else if (list) { | |
| var value = list[0]; | |
| var idx = 1; | |
| } else { | |
| return null; | |
| } | |
| for (; idx < list.length; idx++) { | |
| value = func(value, list[idx]); | |
| } | |
| return value; | |
| }, | |
| __ntuplecomp: function (a, b) { | |
| var mlen = Math.max(a.length, b.length); | |
| for (var i = 0; i < mlen; i++) { | |
| if (a[i] < b[i]) return -1; | |
| if (a[i] > b[i]) return 1; | |
| } | |
| return a.length == b.length ? 0 : (a.length < b.length ? -1 : 1); | |
| }, | |
| __calculate_ratio: function (matches, length) { | |
| return length ? 2.0 * matches / length : 1.0; | |
| }, | |
| __isindict: function (dict) { | |
| return function (key) { return dict.hasOwnProperty(key); }; | |
| }, | |
| __dictget: function (dict, key, defaultValue) { | |
| return dict.hasOwnProperty(key) ? dict[key] : defaultValue; | |
| }, | |
| SequenceMatcher: function (a, b, isjunk) { | |
| this.set_seqs = function (a, b) { | |
| this.set_seq1(a); | |
| this.set_seq2(b); | |
| } | |
| this.set_seq1 = function (a) { | |
| if (a == this.a) return; | |
| this.a = a; | |
| this.matching_blocks = this.opcodes = null; | |
| } | |
| this.set_seq2 = function (b) { | |
| if (b == this.b) return; | |
| this.b = b; | |
| this.matching_blocks = this.opcodes = this.fullbcount = null; | |
| this.__chain_b(); | |
| } | |
| this.__chain_b = function () { | |
| var b = this.b; | |
| var n = b.length; | |
| var b2j = this.b2j = {}; | |
| var populardict = {}; | |
| for (var i = 0; i < b.length; i++) { | |
| var elt = b[i]; | |
| if (b2j.hasOwnProperty(elt)) { | |
| var indices = b2j[elt]; | |
| if (n >= 200 && indices.length * 100 > n) { | |
| populardict[elt] = 1; | |
| delete b2j[elt]; | |
| } else { | |
| indices.push(i); | |
| } | |
| } else { | |
| b2j[elt] = [i]; | |
| } | |
| } | |
| for (var elt in populardict) { | |
| if (populardict.hasOwnProperty(elt)) { | |
| delete b2j[elt]; | |
| } | |
| } | |
| var isjunk = this.isjunk; | |
| var junkdict = {}; | |
| if (isjunk) { | |
| for (var elt in populardict) { | |
| if (populardict.hasOwnProperty(elt) && isjunk(elt)) { | |
| junkdict[elt] = 1; | |
| delete populardict[elt]; | |
| } | |
| } | |
| for (var elt in b2j) { | |
| if (b2j.hasOwnProperty(elt) && isjunk(elt)) { | |
| junkdict[elt] = 1; | |
| delete b2j[elt]; | |
| } | |
| } | |
| } | |
| this.isbjunk = difflib.__isindict(junkdict); | |
| this.isbpopular = difflib.__isindict(populardict); | |
| } | |
| this.find_longest_match = function (alo, ahi, blo, bhi) { | |
| var a = this.a; | |
| var b = this.b; | |
| var b2j = this.b2j; | |
| var isbjunk = this.isbjunk; | |
| var besti = alo; | |
| var bestj = blo; | |
| var bestsize = 0; | |
| var j = null; | |
| var j2len = {}; | |
| var nothing = []; | |
| for (var i = alo; i < ahi; i++) { | |
| var newj2len = {}; | |
| var jdict = difflib.__dictget(b2j, a[i], nothing); | |
| for (var jkey in jdict) { | |
| if (jdict.hasOwnProperty(jkey)) { | |
| j = jdict[jkey]; | |
| if (j < blo) continue; | |
| if (j >= bhi) break; | |
| newj2len[j] = k = difflib.__dictget(j2len, j - 1, 0) + 1; | |
| if (k > bestsize) { | |
| besti = i - k + 1; | |
| bestj = j - k + 1; | |
| bestsize = k; | |
| } | |
| } | |
| } | |
| j2len = newj2len; | |
| } | |
| while (besti > alo && bestj > blo && !isbjunk(b[bestj - 1]) && a[besti - 1] == b[bestj - 1]) { | |
| besti--; | |
| bestj--; | |
| bestsize++; | |
| } | |
| while (besti + bestsize < ahi && bestj + bestsize < bhi && | |
| !isbjunk(b[bestj + bestsize]) && | |
| a[besti + bestsize] == b[bestj + bestsize]) { | |
| bestsize++; | |
| } | |
| while (besti > alo && bestj > blo && isbjunk(b[bestj - 1]) && a[besti - 1] == b[bestj - 1]) { | |
| besti--; | |
| bestj--; | |
| bestsize++; | |
| } | |
| while (besti + bestsize < ahi && bestj + bestsize < bhi && isbjunk(b[bestj + bestsize]) && | |
| a[besti + bestsize] == b[bestj + bestsize]) { | |
| bestsize++; | |
| } | |
| return [besti, bestj, bestsize]; | |
| } | |
| this.get_matching_blocks = function () { | |
| if (this.matching_blocks != null) return this.matching_blocks; | |
| var la = this.a.length; | |
| var lb = this.b.length; | |
| var queue = [[0, la, 0, lb]]; | |
| var matching_blocks = []; | |
| var alo, ahi, blo, bhi, qi, i, j, k, x; | |
| while (queue.length) { | |
| qi = queue.pop(); | |
| alo = qi[0]; | |
| ahi = qi[1]; | |
| blo = qi[2]; | |
| bhi = qi[3]; | |
| x = this.find_longest_match(alo, ahi, blo, bhi); | |
| i = x[0]; | |
| j = x[1]; | |
| k = x[2]; | |
| if (k) { | |
| matching_blocks.push(x); | |
| if (alo < i && blo < j) | |
| queue.push([alo, i, blo, j]); | |
| if (i+k < ahi && j+k < bhi) | |
| queue.push([i + k, ahi, j + k, bhi]); | |
| } | |
| } | |
| matching_blocks.sort(difflib.__ntuplecomp); | |
| var i1 = j1 = k1 = block = 0; | |
| var non_adjacent = []; | |
| for (var idx in matching_blocks) { | |
| if (matching_blocks.hasOwnProperty(idx)) { | |
| block = matching_blocks[idx]; | |
| i2 = block[0]; | |
| j2 = block[1]; | |
| k2 = block[2]; | |
| if (i1 + k1 == i2 && j1 + k1 == j2) { | |
| k1 += k2; | |
| } else { | |
| if (k1) non_adjacent.push([i1, j1, k1]); | |
| i1 = i2; | |
| j1 = j2; | |
| k1 = k2; | |
| } | |
| } | |
| } | |
| if (k1) non_adjacent.push([i1, j1, k1]); | |
| non_adjacent.push([la, lb, 0]); | |
| this.matching_blocks = non_adjacent; | |
| return this.matching_blocks; | |
| } | |
| this.get_opcodes = function () { | |
| if (this.opcodes != null) return this.opcodes; | |
| var i = 0; | |
| var j = 0; | |
| var answer = []; | |
| this.opcodes = answer; | |
| var block, ai, bj, size, tag; | |
| var blocks = this.get_matching_blocks(); | |
| for (var idx in blocks) { | |
| if (blocks.hasOwnProperty(idx)) { | |
| block = blocks[idx]; | |
| ai = block[0]; | |
| bj = block[1]; | |
| size = block[2]; | |
| tag = ''; | |
| if (i < ai && j < bj) { | |
| tag = 'replace'; | |
| } else if (i < ai) { | |
| tag = 'delete'; | |
| } else if (j < bj) { | |
| tag = 'insert'; | |
| } | |
| if (tag) answer.push([tag, i, ai, j, bj]); | |
| i = ai + size; | |
| j = bj + size; | |
| if (size) answer.push(['equal', ai, i, bj, j]); | |
| } | |
| } | |
| return answer; | |
| } | |
| this.get_grouped_opcodes = function (n) { | |
| if (!n) n = 3; | |
| var codes = this.get_opcodes(); | |
| if (!codes) codes = [["equal", 0, 1, 0, 1]]; | |
| var code, tag, i1, i2, j1, j2; | |
| if (codes[0][0] == 'equal') { | |
| code = codes[0]; | |
| tag = code[0]; | |
| i1 = code[1]; | |
| i2 = code[2]; | |
| j1 = code[3]; | |
| j2 = code[4]; | |
| codes[0] = [tag, Math.max(i1, i2 - n), i2, Math.max(j1, j2 - n), j2]; | |
| } | |
| if (codes[codes.length - 1][0] == 'equal') { | |
| code = codes[codes.length - 1]; | |
| tag = code[0]; | |
| i1 = code[1]; | |
| i2 = code[2]; | |
| j1 = code[3]; | |
| j2 = code[4]; | |
| codes[codes.length - 1] = [tag, i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)]; | |
| } | |
| var nn = n + n; | |
| var groups = []; | |
| for (var idx in codes) { | |
| if (codes.hasOwnProperty(idx)) { | |
| code = codes[idx]; | |
| tag = code[0]; | |
| i1 = code[1]; | |
| i2 = code[2]; | |
| j1 = code[3]; | |
| j2 = code[4]; | |
| if (tag == 'equal' && i2 - i1 > nn) { | |
| groups.push([tag, i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)]); | |
| i1 = Math.max(i1, i2-n); | |
| j1 = Math.max(j1, j2-n); | |
| } | |
| groups.push([tag, i1, i2, j1, j2]); | |
| } | |
| } | |
| if (groups && groups[groups.length - 1][0] == 'equal') groups.pop(); | |
| return groups; | |
| } | |
| this.ratio = function () { | |
| matches = difflib.__reduce( | |
| function (sum, triple) { return sum + triple[triple.length - 1]; }, | |
| this.get_matching_blocks(), 0); | |
| return difflib.__calculate_ratio(matches, this.a.length + this.b.length); | |
| } | |
| this.quick_ratio = function () { | |
| var fullbcount, elt; | |
| if (this.fullbcount == null) { | |
| this.fullbcount = fullbcount = {}; | |
| for (var i = 0; i < this.b.length; i++) { | |
| elt = this.b[i]; | |
| fullbcount[elt] = difflib.__dictget(fullbcount, elt, 0) + 1; | |
| } | |
| } | |
| fullbcount = this.fullbcount; | |
| var avail = {}; | |
| var availhas = difflib.__isindict(avail); | |
| var matches = numb = 0; | |
| for (var i = 0; i < this.a.length; i++) { | |
| elt = this.a[i]; | |
| if (availhas(elt)) { | |
| numb = avail[elt]; | |
| } else { | |
| numb = difflib.__dictget(fullbcount, elt, 0); | |
| } | |
| avail[elt] = numb - 1; | |
| if (numb > 0) matches++; | |
| } | |
| return difflib.__calculate_ratio(matches, this.a.length + this.b.length); | |
| } | |
| this.real_quick_ratio = function () { | |
| var la = this.a.length; | |
| var lb = this.b.length; | |
| return _calculate_ratio(Math.min(la, lb), la + lb); | |
| } | |
| this.isjunk = isjunk ? isjunk : difflib.defaultJunkFunction; | |
| this.a = this.b = null; | |
| this.set_seqs(a, b); | |
| } | |
| } | |
| Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction) | |
| { | |
| var startNode; | |
| var startOffset = 0; | |
| var endNode; | |
| var endOffset = 0; | |
| if (!stayWithinNode) | |
| stayWithinNode = this; | |
| if (!direction || direction === "backward" || direction === "both") { | |
| var node = this; | |
| while (node) { | |
| if (node === stayWithinNode) { | |
| if (!startNode) | |
| startNode = stayWithinNode; | |
| break; | |
| } | |
| if (node.nodeType === Node.TEXT_NODE) { | |
| var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1)); | |
| for (var i = start; i >= 0; --i) { | |
| if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) { | |
| startNode = node; | |
| startOffset = i + 1; | |
| break; | |
| } | |
| } | |
| } | |
| if (startNode) | |
| break; | |
| node = node.traversePreviousNode(stayWithinNode); | |
| } | |
| if (!startNode) { | |
| startNode = stayWithinNode; | |
| startOffset = 0; | |
| } | |
| } else { | |
| startNode = this; | |
| startOffset = offset; | |
| } | |
| if (!direction || direction === "forward" || direction === "both") { | |
| node = this; | |
| while (node) { | |
| if (node === stayWithinNode) { | |
| if (!endNode) | |
| endNode = stayWithinNode; | |
| break; | |
| } | |
| if (node.nodeType === Node.TEXT_NODE) { | |
| var start = (node === this ? offset : 0); | |
| for (var i = start; i < node.nodeValue.length; ++i) { | |
| if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) { | |
| endNode = node; | |
| endOffset = i; | |
| break; | |
| } | |
| } | |
| } | |
| if (endNode) | |
| break; | |
| node = node.traverseNextNode(stayWithinNode); | |
| } | |
| if (!endNode) { | |
| endNode = stayWithinNode; | |
| endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length; | |
| } | |
| } else { | |
| endNode = this; | |
| endOffset = offset; | |
| } | |
| var result = this.ownerDocument.createRange(); | |
| result.setStart(startNode, startOffset); | |
| result.setEnd(endNode, endOffset); | |
| return result; | |
| } | |
| Node.prototype.traverseNextTextNode = function(stayWithin) | |
| { | |
| var node = this.traverseNextNode(stayWithin); | |
| if (!node) | |
| return; | |
| while (node && node.nodeType !== Node.TEXT_NODE) | |
| node = node.traverseNextNode(stayWithin); | |
| return node; | |
| } | |
| Node.prototype.rangeBoundaryForOffset = function(offset) | |
| { | |
| var node = this.traverseNextTextNode(this); | |
| while (node && offset > node.nodeValue.length) { | |
| offset -= node.nodeValue.length; | |
| node = node.traverseNextTextNode(this); | |
| } | |
| if (!node) | |
| return { container: this, offset: 0 }; | |
| return { container: node, offset: offset }; | |
| } | |
| Element.prototype.removeStyleClass = function(className) | |
| { | |
| this.classList.remove(className); | |
| } | |
| Element.prototype.removeMatchingStyleClasses = function(classNameRegex) | |
| { | |
| var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)"); | |
| if (regex.test(this.className)) | |
| this.className = this.className.replace(regex, " "); | |
| } | |
| Element.prototype.addStyleClass = function(className) | |
| { | |
| this.classList.add(className); | |
| } | |
| Element.prototype.hasStyleClass = function(className) | |
| { | |
| return this.classList.contains(className); | |
| } | |
| Element.prototype.positionAt = function(x, y) | |
| { | |
| this.style.left = x + "px"; | |
| this.style.top = y + "px"; | |
| } | |
| Element.prototype.pruneEmptyTextNodes = function() | |
| { | |
| var sibling = this.firstChild; | |
| while (sibling) { | |
| var nextSibling = sibling.nextSibling; | |
| if (sibling.nodeType === this.TEXT_NODE && sibling.nodeValue === "") | |
| this.removeChild(sibling); | |
| sibling = nextSibling; | |
| } | |
| } | |
| Element.prototype.isScrolledToBottom = function() | |
| { | |
| return this.scrollTop + this.clientHeight === this.scrollHeight; | |
| } | |
| Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) | |
| { | |
| for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) | |
| for (var i = 0; i < nameArray.length; ++i) | |
| if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) | |
| return node; | |
| return null; | |
| } | |
| Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) | |
| { | |
| return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]); | |
| } | |
| Node.prototype.enclosingNodeOrSelfWithClass = function(className) | |
| { | |
| for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) | |
| if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className)) | |
| return node; | |
| return null; | |
| } | |
| Node.prototype.enclosingNodeWithClass = function(className) | |
| { | |
| if (!this.parentNode) | |
| return null; | |
| return this.parentNode.enclosingNodeOrSelfWithClass(className); | |
| } | |
| Element.prototype.query = function(query) | |
| { | |
| return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; | |
| } | |
| Element.prototype.removeChildren = function() | |
| { | |
| if (this.firstChild) | |
| this.textContent = ""; | |
| } | |
| Element.prototype.isInsertionCaretInside = function() | |
| { | |
| var selection = window.getSelection(); | |
| if (!selection.rangeCount || !selection.isCollapsed) | |
| return false; | |
| var selectionRange = selection.getRangeAt(0); | |
| return selectionRange.startContainer.isSelfOrDescendant(this); | |
| } | |
| Element.prototype.createChild = function(elementName, className) | |
| { | |
| var element = this.ownerDocument.createElement(elementName); | |
| if (className) | |
| element.className = className; | |
| this.appendChild(element); | |
| return element; | |
| } | |
| DocumentFragment.prototype.createChild = Element.prototype.createChild; | |
| Element.prototype.createTextChild = function(text) | |
| { | |
| var element = this.ownerDocument.createTextNode(text); | |
| this.appendChild(element); | |
| return element; | |
| } | |
| DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild; | |
| Element.prototype.totalOffsetLeft = function() | |
| { | |
| return this.totalOffset().left; | |
| } | |
| Element.prototype.totalOffsetTop = function() | |
| { | |
| return this.totalOffset().top; | |
| } | |
| Element.prototype.totalOffset = function() | |
| { | |
| var totalLeft = 0; | |
| var totalTop = 0; | |
| for (var element = this; element; element = element.offsetParent) { | |
| totalLeft += element.offsetLeft; | |
| totalTop += element.offsetTop; | |
| if (this !== element) { | |
| totalLeft += element.clientLeft - element.scrollLeft; | |
| totalTop += element.clientTop - element.scrollTop; | |
| } | |
| } | |
| return { left: totalLeft, top: totalTop }; | |
| } | |
| Element.prototype.scrollOffset = function() | |
| { | |
| var curLeft = 0; | |
| var curTop = 0; | |
| for (var element = this; element; element = element.scrollParent) { | |
| curLeft += element.scrollLeft; | |
| curTop += element.scrollTop; | |
| } | |
| return { left: curLeft, top: curTop }; | |
| } | |
| function AnchorBox(x, y, width, height) | |
| { | |
| this.x = x || 0; | |
| this.y = y || 0; | |
| this.width = width || 0; | |
| this.height = height || 0; | |
| } | |
| Element.prototype.offsetRelativeToWindow = function(targetWindow) | |
| { | |
| var elementOffset = new AnchorBox(); | |
| var curElement = this; | |
| var curWindow = this.ownerDocument.defaultView; | |
| while (curWindow && curElement) { | |
| elementOffset.x += curElement.totalOffsetLeft(); | |
| elementOffset.y += curElement.totalOffsetTop(); | |
| if (curWindow === targetWindow) | |
| break; | |
| curElement = curWindow.frameElement; | |
| curWindow = curWindow.parent; | |
| } | |
| return elementOffset; | |
| } | |
| Element.prototype.boxInWindow = function(targetWindow) | |
| { | |
| targetWindow = targetWindow || this.ownerDocument.defaultView; | |
| var anchorBox = this.offsetRelativeToWindow(window); | |
| anchorBox.width = Math.min(this.offsetWidth, window.innerWidth - anchorBox.x); | |
| anchorBox.height = Math.min(this.offsetHeight, window.innerHeight - anchorBox.y); | |
| return anchorBox; | |
| } | |
| Element.prototype.setTextAndTitle = function(text) | |
| { | |
| this.textContent = text; | |
| this.title = text; | |
| } | |
| KeyboardEvent.prototype.__defineGetter__("data", function() | |
| { | |
| switch (this.type) { | |
| case "keypress": | |
| if (!this.ctrlKey && !this.metaKey) | |
| return String.fromCharCode(this.charCode); | |
| else | |
| return ""; | |
| case "keydown": | |
| case "keyup": | |
| if (!this.ctrlKey && !this.metaKey && !this.altKey) | |
| return String.fromCharCode(this.which); | |
| else | |
| return ""; | |
| } | |
| }); | |
| Event.prototype.consume = function(preventDefault) | |
| { | |
| this.stopImmediatePropagation(); | |
| if (preventDefault) | |
| this.preventDefault(); | |
| this.handled = true; | |
| } | |
| Text.prototype.select = function(start, end) | |
| { | |
| start = start || 0; | |
| end = end || this.textContent.length; | |
| if (start < 0) | |
| start = end + start; | |
| var selection = this.ownerDocument.defaultView.getSelection(); | |
| selection.removeAllRanges(); | |
| var range = this.ownerDocument.createRange(); | |
| range.setStart(this, start); | |
| range.setEnd(this, end); | |
| selection.addRange(range); | |
| return this; | |
| } | |
| Element.prototype.selectionLeftOffset = function() | |
| { | |
| var selection = window.getSelection(); | |
| if (!selection.containsNode(this, true)) | |
| return null; | |
| var leftOffset = selection.anchorOffset; | |
| var node = selection.anchorNode; | |
| while (node !== this) { | |
| while (node.previousSibling) { | |
| node = node.previousSibling; | |
| leftOffset += node.textContent.length; | |
| } | |
| node = node.parentNode; | |
| } | |
| return leftOffset; | |
| } | |
| Node.prototype.isAncestor = function(node) | |
| { | |
| if (!node) | |
| return false; | |
| var currentNode = node.parentNode; | |
| while (currentNode) { | |
| if (this === currentNode) | |
| return true; | |
| currentNode = currentNode.parentNode; | |
| } | |
| return false; | |
| } | |
| Node.prototype.isDescendant = function(descendant) | |
| { | |
| return !!descendant && descendant.isAncestor(this); | |
| } | |
| Node.prototype.isSelfOrAncestor = function(node) | |
| { | |
| return !!node && (node === this || this.isAncestor(node)); | |
| } | |
| Node.prototype.isSelfOrDescendant = function(node) | |
| { | |
| return !!node && (node === this || this.isDescendant(node)); | |
| } | |
| Node.prototype.traverseNextNode = function(stayWithin) | |
| { | |
| var node = this.firstChild; | |
| if (node) | |
| return node; | |
| if (stayWithin && this === stayWithin) | |
| return null; | |
| node = this.nextSibling; | |
| if (node) | |
| return node; | |
| node = this; | |
| while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin)) | |
| node = node.parentNode; | |
| if (!node) | |
| return null; | |
| return node.nextSibling; | |
| } | |
| Node.prototype.traversePreviousNode = function(stayWithin) | |
| { | |
| if (stayWithin && this === stayWithin) | |
| return null; | |
| var node = this.previousSibling; | |
| while (node && node.lastChild) | |
| node = node.lastChild; | |
| if (node) | |
| return node; | |
| return this.parentNode; | |
| } | |
| HTMLTextAreaElement.prototype.moveCursorToEnd = function() | |
| { | |
| var length = this.value.length; | |
| this.setSelectionRange(length, length); | |
| } | |
| function isEnterKey(event) { | |
| return event.keyCode !== 229 && event.keyIdentifier === "Enter"; | |
| } | |
| function consumeEvent(e) | |
| { | |
| e.consume(); | |
| } | |
| function TreeOutline(listNode, nonFocusable) | |
| { | |
| this.children = []; | |
| this.selectedTreeElement = null; | |
| this._childrenListNode = listNode; | |
| this.childrenListElement = this._childrenListNode; | |
| this._childrenListNode.removeChildren(); | |
| this.expandTreeElementsWhenArrowing = false; | |
| this.root = true; | |
| this.hasChildren = false; | |
| this.expanded = true; | |
| this.selected = false; | |
| this.treeOutline = this; | |
| this.comparator = null; | |
| this.searchable = false; | |
| this.searchInputElement = null; | |
| this.setFocusable(!nonFocusable); | |
| this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true); | |
| this._childrenListNode.addEventListener("keypress", this._treeKeyPress.bind(this), true); | |
| this._treeElementsMap = new Map(); | |
| this._expandedStateMap = new Map(); | |
| } | |
| TreeOutline.prototype.setFocusable = function(focusable) | |
| { | |
| if (focusable) | |
| this._childrenListNode.setAttribute("tabIndex", 0); | |
| else | |
| this._childrenListNode.removeAttribute("tabIndex"); | |
| } | |
| TreeOutline.prototype.appendChild = function(child) | |
| { | |
| var insertionIndex; | |
| if (this.treeOutline.comparator) | |
| insertionIndex = insertionIndexForObjectInListSortedByFunction(child, this.children, this.treeOutline.comparator); | |
| else | |
| insertionIndex = this.children.length; | |
| this.insertChild(child, insertionIndex); | |
| } | |
| TreeOutline.prototype.insertChild = function(child, index) | |
| { | |
| if (!child) | |
| throw("child can't be undefined or null"); | |
| var previousChild = (index > 0 ? this.children[index - 1] : null); | |
| if (previousChild) { | |
| previousChild.nextSibling = child; | |
| child.previousSibling = previousChild; | |
| } else { | |
| child.previousSibling = null; | |
| } | |
| var nextChild = this.children[index]; | |
| if (nextChild) { | |
| nextChild.previousSibling = child; | |
| child.nextSibling = nextChild; | |
| } else { | |
| child.nextSibling = null; | |
| } | |
| this.children.splice(index, 0, child); | |
| this.hasChildren = true; | |
| child.parent = this; | |
| child.treeOutline = this.treeOutline; | |
| child.treeOutline._rememberTreeElement(child); | |
| var current = child.children[0]; | |
| while (current) { | |
| current.treeOutline = this.treeOutline; | |
| current.treeOutline._rememberTreeElement(current); | |
| current = current.traverseNextTreeElement(false, child, true); | |
| } | |
| if (child.hasChildren && typeof(child.treeOutline._expandedStateMap.get(child.representedObject)) !== "undefined") | |
| child.expanded = child.treeOutline._expandedStateMap.get(child.representedObject); | |
| if (!this._childrenListNode) { | |
| this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); | |
| this._childrenListNode.parentTreeElement = this; | |
| this._childrenListNode.classList.add("children"); | |
| if (this.hidden) | |
| this._childrenListNode.classList.add("hidden"); | |
| } | |
| child._attach(); | |
| } | |
| TreeOutline.prototype.removeChildAtIndex = function(childIndex) | |
| { | |
| if (childIndex < 0 || childIndex >= this.children.length) | |
| throw("childIndex out of range"); | |
| var child = this.children[childIndex]; | |
| this.children.splice(childIndex, 1); | |
| var parent = child.parent; | |
| if (child.deselect()) { | |
| if (child.previousSibling) | |
| child.previousSibling.select(); | |
| else if (child.nextSibling) | |
| child.nextSibling.select(); | |
| else | |
| parent.select(); | |
| } | |
| if (child.previousSibling) | |
| child.previousSibling.nextSibling = child.nextSibling; | |
| if (child.nextSibling) | |
| child.nextSibling.previousSibling = child.previousSibling; | |
| if (child.treeOutline) { | |
| child.treeOutline._forgetTreeElement(child); | |
| child.treeOutline._forgetChildrenRecursive(child); | |
| } | |
| child._detach(); | |
| child.treeOutline = null; | |
| child.parent = null; | |
| child.nextSibling = null; | |
| child.previousSibling = null; | |
| } | |
| TreeOutline.prototype.removeChild = function(child) | |
| { | |
| if (!child) | |
| throw("child can't be undefined or null"); | |
| var childIndex = this.children.indexOf(child); | |
| if (childIndex === -1) | |
| throw("child not found in this node's children"); | |
| this.removeChildAtIndex.call(this, childIndex); | |
| } | |
| TreeOutline.prototype.removeChildren = function() | |
| { | |
| for (var i = 0; i < this.children.length; ++i) { | |
| var child = this.children[i]; | |
| child.deselect(); | |
| if (child.treeOutline) { | |
| child.treeOutline._forgetTreeElement(child); | |
| child.treeOutline._forgetChildrenRecursive(child); | |
| } | |
| child._detach(); | |
| child.treeOutline = null; | |
| child.parent = null; | |
| child.nextSibling = null; | |
| child.previousSibling = null; | |
| } | |
| this.children = []; | |
| } | |
| TreeOutline.prototype._rememberTreeElement = function(element) | |
| { | |
| if (!this._treeElementsMap.get(element.representedObject)) | |
| this._treeElementsMap.put(element.representedObject, []); | |
| var elements = this._treeElementsMap.get(element.representedObject); | |
| if (elements.indexOf(element) !== -1) | |
| return; | |
| elements.push(element); | |
| } | |
| TreeOutline.prototype._forgetTreeElement = function(element) | |
| { | |
| if (this._treeElementsMap.get(element.representedObject)) | |
| this._treeElementsMap.get(element.representedObject).remove(element, true); | |
| } | |
| TreeOutline.prototype._forgetChildrenRecursive = function(parentElement) | |
| { | |
| var child = parentElement.children[0]; | |
| while (child) { | |
| this._forgetTreeElement(child); | |
| child = child.traverseNextTreeElement(false, parentElement, true); | |
| } | |
| } | |
| TreeOutline.prototype.getCachedTreeElement = function(representedObject) | |
| { | |
| if (!representedObject) | |
| return null; | |
| var elements = this._treeElementsMap.get(representedObject); | |
| if (elements && elements.length) | |
| return elements[0]; | |
| return null; | |
| } | |
| TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) | |
| { | |
| if (!representedObject) | |
| return null; | |
| var cachedElement = this.getCachedTreeElement(representedObject); | |
| if (cachedElement) | |
| return cachedElement; | |
| var item; | |
| var found = false; | |
| for (var i = 0; i < this.children.length; ++i) { | |
| item = this.children[i]; | |
| if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) { | |
| found = true; | |
| break; | |
| } | |
| } | |
| if (!found) | |
| return null; | |
| var ancestors = []; | |
| var currentObject = representedObject; | |
| while (currentObject) { | |
| ancestors.unshift(currentObject); | |
| if (currentObject === item.representedObject) | |
| break; | |
| currentObject = getParent(currentObject); | |
| } | |
| for (var i = 0; i < ancestors.length; ++i) { | |
| if (ancestors[i] === representedObject) | |
| continue; | |
| item = this.findTreeElement(ancestors[i], isAncestor, getParent); | |
| if (item) | |
| item.onpopulate(); | |
| } | |
| return this.getCachedTreeElement(representedObject); | |
| } | |
| TreeOutline.prototype.treeElementFromPoint = function(x, y) | |
| { | |
| var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y); | |
| if (!node) | |
| return null; | |
| var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]); | |
| if (listNode) | |
| return listNode.parentTreeElement || listNode.treeElement; | |
| return null; | |
| } | |
| TreeOutline.prototype._treeKeyPress = function(event) | |
| { | |
| if (!this.searchable || WebInspector.isBeingEdited(this._childrenListNode)) | |
| return; | |
| var searchText = String.fromCharCode(event.charCode); | |
| if (searchText.trim() !== searchText) | |
| return; | |
| this._startSearch(searchText); | |
| event.consume(true); | |
| } | |
| TreeOutline.prototype._treeKeyDown = function(event) | |
| { | |
| if (event.target !== this._childrenListNode) | |
| return; | |
| if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey) | |
| return; | |
| var handled = false; | |
| var nextSelectedElement; | |
| if (event.keyIdentifier === "Up" && !event.altKey) { | |
| nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true); | |
| while (nextSelectedElement && !nextSelectedElement.selectable) | |
| nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing); | |
| handled = nextSelectedElement ? true : false; | |
| } else if (event.keyIdentifier === "Down" && !event.altKey) { | |
| nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true); | |
| while (nextSelectedElement && !nextSelectedElement.selectable) | |
| nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing); | |
| handled = nextSelectedElement ? true : false; | |
| } else if (event.keyIdentifier === "Left") { | |
| if (this.selectedTreeElement.expanded) { | |
| if (event.altKey) | |
| this.selectedTreeElement.collapseRecursively(); | |
| else | |
| this.selectedTreeElement.collapse(); | |
| handled = true; | |
| } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) { | |
| handled = true; | |
| if (this.selectedTreeElement.parent.selectable) { | |
| nextSelectedElement = this.selectedTreeElement.parent; | |
| while (nextSelectedElement && !nextSelectedElement.selectable) | |
| nextSelectedElement = nextSelectedElement.parent; | |
| handled = nextSelectedElement ? true : false; | |
| } else if (this.selectedTreeElement.parent) | |
| this.selectedTreeElement.parent.collapse(); | |
| } | |
| } else if (event.keyIdentifier === "Right") { | |
| if (!this.selectedTreeElement.revealed()) { | |
| this.selectedTreeElement.reveal(); | |
| handled = true; | |
| } else if (this.selectedTreeElement.hasChildren) { | |
| handled = true; | |
| if (this.selectedTreeElement.expanded) { | |
| nextSelectedElement = this.selectedTreeElement.children[0]; | |
| while (nextSelectedElement && !nextSelectedElement.selectable) | |
| nextSelectedElement = nextSelectedElement.nextSibling; | |
| handled = nextSelectedElement ? true : false; | |
| } else { | |
| if (event.altKey) | |
| this.selectedTreeElement.expandRecursively(); | |
| else | |
| this.selectedTreeElement.expand(); | |
| } | |
| } | |
| } else if (event.keyCode === 8 || event.keyCode === 46 ) | |
| handled = this.selectedTreeElement.ondelete(); | |
| else if (isEnterKey(event)) | |
| handled = this.selectedTreeElement.onenter(); | |
| else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code) | |
| handled = this.selectedTreeElement.onspace(); | |
| if (nextSelectedElement) { | |
| nextSelectedElement.reveal(); | |
| nextSelectedElement.select(false, true); | |
| } | |
| if (handled) | |
| event.consume(true); | |
| } | |
| TreeOutline.prototype.expand = function() | |
| { | |
| } | |
| TreeOutline.prototype.collapse = function() | |
| { | |
| } | |
| TreeOutline.prototype.revealed = function() | |
| { | |
| return true; | |
| } | |
| TreeOutline.prototype.reveal = function() | |
| { | |
| } | |
| TreeOutline.prototype.select = function() | |
| { | |
| } | |
| TreeOutline.prototype.revealAndSelect = function(omitFocus) | |
| { | |
| } | |
| TreeOutline.prototype._startSearch = function(searchText) | |
| { | |
| if (!this.searchInputElement || !this.searchable) | |
| return; | |
| this._searching = true; | |
| if (this.searchStarted) | |
| this.searchStarted(); | |
| this.searchInputElement.value = searchText; | |
| function focusSearchInput() | |
| { | |
| this.searchInputElement.focus(); | |
| } | |
| window.setTimeout(focusSearchInput.bind(this), 0); | |
| this._searchTextChanged(); | |
| this._boundSearchTextChanged = this._searchTextChanged.bind(this); | |
| this.searchInputElement.addEventListener("paste", this._boundSearchTextChanged); | |
| this.searchInputElement.addEventListener("cut", this._boundSearchTextChanged); | |
| this.searchInputElement.addEventListener("keypress", this._boundSearchTextChanged); | |
| this._boundSearchInputKeyDown = this._searchInputKeyDown.bind(this); | |
| this.searchInputElement.addEventListener("keydown", this._boundSearchInputKeyDown); | |
| this._boundSearchInputBlur = this._searchInputBlur.bind(this); | |
| this.searchInputElement.addEventListener("blur", this._boundSearchInputBlur); | |
| } | |
| TreeOutline.prototype._searchTextChanged = function() | |
| { | |
| function updateSearch() | |
| { | |
| var nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, false); | |
| if (!nextSelectedElement) | |
| nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.children[0], false); | |
| this._showSearchMatchElement(nextSelectedElement); | |
| } | |
| window.setTimeout(updateSearch.bind(this), 0); | |
| } | |
| TreeOutline.prototype._showSearchMatchElement = function(treeElement) | |
| { | |
| this._currentSearchMatchElement = treeElement; | |
| if (treeElement) { | |
| this._childrenListNode.classList.add("search-match-found"); | |
| this._childrenListNode.classList.remove("search-match-not-found"); | |
| treeElement.revealAndSelect(true); | |
| } else { | |
| this._childrenListNode.classList.remove("search-match-found"); | |
| this._childrenListNode.classList.add("search-match-not-found"); | |
| } | |
| } | |
| TreeOutline.prototype._searchInputKeyDown = function(event) | |
| { | |
| if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) | |
| return; | |
| var handled = false; | |
| var nextSelectedElement; | |
| if (event.keyIdentifier === "Down") { | |
| nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, true); | |
| handled = true; | |
| } else if (event.keyIdentifier === "Up") { | |
| nextSelectedElement = this._previousSearchMatch(this.searchInputElement.value, this.selectedTreeElement); | |
| handled = true; | |
| } else if (event.keyCode === 27 ) { | |
| this._searchFinished(); | |
| handled = true; | |
| } else if (isEnterKey(event)) { | |
| var lastSearchMatchElement = this._currentSearchMatchElement; | |
| this._searchFinished(); | |
| lastSearchMatchElement.onenter(); | |
| handled = true; | |
| } | |
| if (nextSelectedElement) | |
| this._showSearchMatchElement(nextSelectedElement); | |
| if (handled) | |
| event.consume(true); | |
| else | |
| window.setTimeout(this._boundSearchTextChanged, 0); | |
| } | |
| TreeOutline.prototype._nextSearchMatch = function(searchText, startTreeElement, skipStartTreeElement) | |
| { | |
| var currentTreeElement = startTreeElement; | |
| var skipCurrentTreeElement = skipStartTreeElement; | |
| while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) { | |
| currentTreeElement = currentTreeElement.traverseNextTreeElement(true, null, true); | |
| skipCurrentTreeElement = false; | |
| } | |
| return currentTreeElement; | |
| } | |
| TreeOutline.prototype._previousSearchMatch = function(searchText, startTreeElement) | |
| { | |
| var currentTreeElement = startTreeElement; | |
| var skipCurrentTreeElement = true; | |
| while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) { | |
| currentTreeElement = currentTreeElement.traversePreviousTreeElement(true, true); | |
| skipCurrentTreeElement = false; | |
| } | |
| return currentTreeElement; | |
| } | |
| TreeOutline.prototype._searchInputBlur = function(event) | |
| { | |
| this._searchFinished(); | |
| } | |
| TreeOutline.prototype._searchFinished = function() | |
| { | |
| if (!this._searching) | |
| return; | |
| delete this._searching; | |
| this._childrenListNode.classList.remove("search-match-found"); | |
| this._childrenListNode.classList.remove("search-match-not-found"); | |
| delete this._currentSearchMatchElement; | |
| this.searchInputElement.value = ""; | |
| this.searchInputElement.removeEventListener("paste", this._boundSearchTextChanged); | |
| this.searchInputElement.removeEventListener("cut", this._boundSearchTextChanged); | |
| delete this._boundSearchTextChanged; | |
| this.searchInputElement.removeEventListener("keydown", this._boundSearchInputKeyDown); | |
| delete this._boundSearchInputKeyDown; | |
| this.searchInputElement.removeEventListener("blur", this._boundSearchInputBlur); | |
| delete this._boundSearchInputBlur; | |
| if (this.searchFinished) | |
| this.searchFinished(); | |
| this.treeOutline._childrenListNode.focus(); | |
| } | |
| TreeOutline.prototype.stopSearch = function() | |
| { | |
| this._searchFinished(); | |
| } | |
| function TreeElement(title, representedObject, hasChildren) | |
| { | |
| this._title = title; | |
| this.representedObject = (representedObject || {}); | |
| this._hidden = false; | |
| this._selectable = true; | |
| this.expanded = false; | |
| this.selected = false; | |
| this.hasChildren = hasChildren; | |
| this.children = []; | |
| this.treeOutline = null; | |
| this.parent = null; | |
| this.previousSibling = null; | |
| this.nextSibling = null; | |
| this._listItemNode = null; | |
| } | |
| TreeElement.prototype = { | |
| arrowToggleWidth: 10, | |
| get selectable() { | |
| if (this._hidden) | |
| return false; | |
| return this._selectable; | |
| }, | |
| set selectable(x) { | |
| this._selectable = x; | |
| }, | |
| get listItemElement() { | |
| return this._listItemNode; | |
| }, | |
| get childrenListElement() { | |
| return this._childrenListNode; | |
| }, | |
| get title() { | |
| return this._title; | |
| }, | |
| set title(x) { | |
| this._title = x; | |
| this._setListItemNodeContent(); | |
| }, | |
| get tooltip() { | |
| return this._tooltip; | |
| }, | |
| set tooltip(x) { | |
| this._tooltip = x; | |
| if (this._listItemNode) | |
| this._listItemNode.title = x ? x : ""; | |
| }, | |
| get hasChildren() { | |
| return this._hasChildren; | |
| }, | |
| set hasChildren(x) { | |
| if (this._hasChildren === x) | |
| return; | |
| this._hasChildren = x; | |
| if (!this._listItemNode) | |
| return; | |
| if (x) | |
| this._listItemNode.classList.add("parent"); | |
| else { | |
| this._listItemNode.classList.remove("parent"); | |
| this.collapse(); | |
| } | |
| }, | |
| get hidden() { | |
| return this._hidden; | |
| }, | |
| set hidden(x) { | |
| if (this._hidden === x) | |
| return; | |
| this._hidden = x; | |
| if (x) { | |
| if (this._listItemNode) | |
| this._listItemNode.classList.add("hidden"); | |
| if (this._childrenListNode) | |
| this._childrenListNode.classList.add("hidden"); | |
| } else { | |
| if (this._listItemNode) | |
| this._listItemNode.classList.remove("hidden"); | |
| if (this._childrenListNode) | |
| this._childrenListNode.classList.remove("hidden"); | |
| } | |
| }, | |
| get shouldRefreshChildren() { | |
| return this._shouldRefreshChildren; | |
| }, | |
| set shouldRefreshChildren(x) { | |
| this._shouldRefreshChildren = x; | |
| if (x && this.expanded) | |
| this.expand(); | |
| }, | |
| _setListItemNodeContent: function() | |
| { | |
| if (!this._listItemNode) | |
| return; | |
| if (typeof this._title === "string") | |
| this._listItemNode.textContent = this._title; | |
| else { | |
| this._listItemNode.removeChildren(); | |
| if (this._title) | |
| this._listItemNode.appendChild(this._title); | |
| } | |
| } | |
| } | |
| TreeElement.prototype.appendChild = TreeOutline.prototype.appendChild; | |
| TreeElement.prototype.insertChild = TreeOutline.prototype.insertChild; | |
| TreeElement.prototype.removeChild = TreeOutline.prototype.removeChild; | |
| TreeElement.prototype.removeChildAtIndex = TreeOutline.prototype.removeChildAtIndex; | |
| TreeElement.prototype.removeChildren = TreeOutline.prototype.removeChildren; | |
| TreeElement.prototype._attach = function() | |
| { | |
| if (!this._listItemNode || this.parent._shouldRefreshChildren) { | |
| if (this._listItemNode && this._listItemNode.parentNode) | |
| this._listItemNode.parentNode.removeChild(this._listItemNode); | |
| this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li"); | |
| this._listItemNode.treeElement = this; | |
| this._setListItemNodeContent(); | |
| this._listItemNode.title = this._tooltip ? this._tooltip : ""; | |
| if (this.hidden) | |
| this._listItemNode.classList.add("hidden"); | |
| if (this.hasChildren) | |
| this._listItemNode.classList.add("parent"); | |
| if (this.expanded) | |
| this._listItemNode.classList.add("expanded"); | |
| if (this.selected) | |
| this._listItemNode.classList.add("selected"); | |
| this._listItemNode.addEventListener("mousedown", TreeElement.treeElementMouseDown, false); | |
| this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false); | |
| this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false); | |
| this.onattach(); | |
| } | |
| var nextSibling = null; | |
| if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode) | |
| nextSibling = this.nextSibling._listItemNode; | |
| this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling); | |
| if (this._childrenListNode) | |
| this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); | |
| if (this.selected) | |
| this.select(); | |
| if (this.expanded) | |
| this.expand(); | |
| } | |
| TreeElement.prototype._detach = function() | |
| { | |
| if (this._listItemNode && this._listItemNode.parentNode) | |
| this._listItemNode.parentNode.removeChild(this._listItemNode); | |
| if (this._childrenListNode && this._childrenListNode.parentNode) | |
| this._childrenListNode.parentNode.removeChild(this._childrenListNode); | |
| } | |
| TreeElement.treeElementMouseDown = function(event) | |
| { | |
| var element = event.currentTarget; | |
| if (!element || !element.treeElement || !element.treeElement.selectable) | |
| return; | |
| if (element.treeElement.isEventWithinDisclosureTriangle(event)) | |
| return; | |
| element.treeElement.selectOnMouseDown(event); | |
| } | |
| TreeElement.treeElementToggled = function(event) | |
| { | |
| var element = event.currentTarget; | |
| if (!element || !element.treeElement) | |
| return; | |
| var toggleOnClick = element.treeElement.toggleOnClick && !element.treeElement.selectable; | |
| var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event); | |
| if (!toggleOnClick && !isInTriangle) | |
| return; | |
| if (element.treeElement.expanded) { | |
| if (event.altKey) | |
| element.treeElement.collapseRecursively(); | |
| else | |
| element.treeElement.collapse(); | |
| } else { | |
| if (event.altKey) | |
| element.treeElement.expandRecursively(); | |
| else | |
| element.treeElement.expand(); | |
| } | |
| event.consume(); | |
| } | |
| TreeElement.treeElementDoubleClicked = function(event) | |
| { | |
| var element = event.currentTarget; | |
| if (!element || !element.treeElement) | |
| return; | |
| var handled = element.treeElement.ondblclick.call(element.treeElement, event); | |
| if (handled) | |
| return; | |
| if (element.treeElement.hasChildren && !element.treeElement.expanded) | |
| element.treeElement.expand(); | |
| } | |
| TreeElement.prototype.collapse = function() | |
| { | |
| if (this._listItemNode) | |
| this._listItemNode.classList.remove("expanded"); | |
| if (this._childrenListNode) | |
| this._childrenListNode.classList.remove("expanded"); | |
| this.expanded = false; | |
| if (this.treeOutline) | |
| this.treeOutline._expandedStateMap.put(this.representedObject, false); | |
| this.oncollapse(); | |
| } | |
| TreeElement.prototype.collapseRecursively = function() | |
| { | |
| var item = this; | |
| while (item) { | |
| if (item.expanded) | |
| item.collapse(); | |
| item = item.traverseNextTreeElement(false, this, true); | |
| } | |
| } | |
| TreeElement.prototype.expand = function() | |
| { | |
| if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)) | |
| return; | |
| this.expanded = true; | |
| if (this.treeOutline) | |
| this.treeOutline._expandedStateMap.put(this.representedObject, true); | |
| if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) { | |
| if (this._childrenListNode && this._childrenListNode.parentNode) | |
| this._childrenListNode.parentNode.removeChild(this._childrenListNode); | |
| this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); | |
| this._childrenListNode.parentTreeElement = this; | |
| this._childrenListNode.classList.add("children"); | |
| if (this.hidden) | |
| this._childrenListNode.classList.add("hidden"); | |
| this.onpopulate(); | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i]._attach(); | |
| delete this._shouldRefreshChildren; | |
| } | |
| if (this._listItemNode) { | |
| this._listItemNode.classList.add("expanded"); | |
| if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode) | |
| this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); | |
| } | |
| if (this._childrenListNode) | |
| this._childrenListNode.classList.add("expanded"); | |
| this.onexpand(); | |
| } | |
| TreeElement.prototype.expandRecursively = function(maxDepth) | |
| { | |
| var item = this; | |
| var info = {}; | |
| var depth = 0; | |
| if (typeof maxDepth === "undefined" || typeof maxDepth === "null") | |
| maxDepth = 3; | |
| while (item) { | |
| if (depth < maxDepth) | |
| item.expand(); | |
| item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info); | |
| depth += info.depthChange; | |
| } | |
| } | |
| TreeElement.prototype.hasAncestor = function(ancestor) { | |
| if (!ancestor) | |
| return false; | |
| var currentNode = this.parent; | |
| while (currentNode) { | |
| if (ancestor === currentNode) | |
| return true; | |
| currentNode = currentNode.parent; | |
| } | |
| return false; | |
| } | |
| TreeElement.prototype.reveal = function() | |
| { | |
| var currentAncestor = this.parent; | |
| while (currentAncestor && !currentAncestor.root) { | |
| if (!currentAncestor.expanded) | |
| currentAncestor.expand(); | |
| currentAncestor = currentAncestor.parent; | |
| } | |
| this.onreveal(this); | |
| } | |
| TreeElement.prototype.revealed = function() | |
| { | |
| var currentAncestor = this.parent; | |
| while (currentAncestor && !currentAncestor.root) { | |
| if (!currentAncestor.expanded) | |
| return false; | |
| currentAncestor = currentAncestor.parent; | |
| } | |
| return true; | |
| } | |
| TreeElement.prototype.selectOnMouseDown = function(event) | |
| { | |
| if (this.select(false, true)) | |
| event.consume(true); | |
| } | |
| TreeElement.prototype.select = function(omitFocus, selectedByUser) | |
| { | |
| if (!this.treeOutline || !this.selectable || this.selected) | |
| return false; | |
| if (this.treeOutline.selectedTreeElement) | |
| this.treeOutline.selectedTreeElement.deselect(); | |
| this.selected = true; | |
| if(!omitFocus) | |
| this.treeOutline._childrenListNode.focus(); | |
| if (!this.treeOutline) | |
| return false; | |
| this.treeOutline.selectedTreeElement = this; | |
| if (this._listItemNode) | |
| this._listItemNode.classList.add("selected"); | |
| return this.onselect(selectedByUser); | |
| } | |
| TreeElement.prototype.revealAndSelect = function(omitFocus) | |
| { | |
| this.reveal(); | |
| this.select(omitFocus); | |
| } | |
| TreeElement.prototype.deselect = function(supressOnDeselect) | |
| { | |
| if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected) | |
| return false; | |
| this.selected = false; | |
| this.treeOutline.selectedTreeElement = null; | |
| if (this._listItemNode) | |
| this._listItemNode.classList.remove("selected"); | |
| return true; | |
| } | |
| TreeElement.prototype.onpopulate = function() { } | |
| TreeElement.prototype.onenter = function() { } | |
| TreeElement.prototype.ondelete = function() { } | |
| TreeElement.prototype.onspace = function() { } | |
| TreeElement.prototype.onattach = function() { } | |
| TreeElement.prototype.onexpand = function() { } | |
| TreeElement.prototype.oncollapse = function() { } | |
| TreeElement.prototype.ondblclick = function() { } | |
| TreeElement.prototype.onreveal = function() { } | |
| TreeElement.prototype.onselect = function(selectedByUser) { } | |
| TreeElement.prototype.traverseNextTreeElement = function(skipUnrevealed, stayWithin, dontPopulate, info) | |
| { | |
| if (!dontPopulate && this.hasChildren) | |
| this.onpopulate(); | |
| if (info) | |
| info.depthChange = 0; | |
| var element = skipUnrevealed ? (this.revealed() ? this.children[0] : null) : this.children[0]; | |
| if (element && (!skipUnrevealed || (skipUnrevealed && this.expanded))) { | |
| if (info) | |
| info.depthChange = 1; | |
| return element; | |
| } | |
| if (this === stayWithin) | |
| return null; | |
| element = skipUnrevealed ? (this.revealed() ? this.nextSibling : null) : this.nextSibling; | |
| if (element) | |
| return element; | |
| element = this; | |
| while (element && !element.root && !(skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) { | |
| if (info) | |
| info.depthChange -= 1; | |
| element = element.parent; | |
| } | |
| if (!element) | |
| return null; | |
| return (skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling); | |
| } | |
| TreeElement.prototype.traversePreviousTreeElement = function(skipUnrevealed, dontPopulate) | |
| { | |
| var element = skipUnrevealed ? (this.revealed() ? this.previousSibling : null) : this.previousSibling; | |
| if (!dontPopulate && element && element.hasChildren) | |
| element.onpopulate(); | |
| while (element && (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) { | |
| if (!dontPopulate && element.hasChildren) | |
| element.onpopulate(); | |
| element = (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]); | |
| } | |
| if (element) | |
| return element; | |
| if (!this.parent || this.parent.root) | |
| return null; | |
| return this.parent; | |
| } | |
| TreeElement.prototype.isEventWithinDisclosureTriangle = function(event) | |
| { | |
| var paddingLeftValue = window.getComputedStyle(this._listItemNode).getPropertyCSSValue("padding-left"); | |
| var computedLeftPadding = paddingLeftValue ? paddingLeftValue.getFloatValue(CSSPrimitiveValue.CSS_PX) : 0; | |
| var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding; | |
| return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren; | |
| } | |
| var WebInspector = { | |
| _panelDescriptors: function() | |
| { | |
| this.panels = {}; | |
| WebInspector.inspectorView = new WebInspector.InspectorView(); | |
| var parentElement = document.getElementById("main"); | |
| WebInspector.inspectorView.show(parentElement); | |
| WebInspector.inspectorView.addEventListener(WebInspector.InspectorView.Events.PanelSelected, this._panelSelected, this); | |
| var elements = new WebInspector.ElementsPanelDescriptor(); | |
| var resources = new WebInspector.PanelDescriptor("resources", WebInspector.UIString("Resources"), "ResourcesPanel", "ResourcesPanel.js"); | |
| var network = new WebInspector.NetworkPanelDescriptor(); | |
| var scripts = new WebInspector.ScriptsPanelDescriptor(); | |
| var timeline = new WebInspector.PanelDescriptor("timeline", WebInspector.UIString("Timeline"), "TimelinePanel", "TimelinePanel.js"); | |
| var profiles = new WebInspector.PanelDescriptor("profiles", WebInspector.UIString("Profiles"), "ProfilesPanel", "ProfilesPanel.js"); | |
| var audits = new WebInspector.PanelDescriptor("audits", WebInspector.UIString("Audits"), "AuditsPanel", "AuditsPanel.js"); | |
| var console = new WebInspector.PanelDescriptor("console", WebInspector.UIString("Console"), "ConsolePanel"); | |
| var allDescriptors = [elements, resources, network, scripts, timeline, profiles, audits, console]; | |
| var panelDescriptors = []; | |
| if (WebInspector.WorkerManager.isWorkerFrontend()) { | |
| panelDescriptors.push(scripts); | |
| panelDescriptors.push(timeline); | |
| panelDescriptors.push(profiles); | |
| panelDescriptors.push(console); | |
| return panelDescriptors; | |
| } | |
| var allDescriptors = [elements, resources, network, scripts, timeline, profiles, audits, console]; | |
| var hiddenPanels = InspectorFrontendHost.hiddenPanels(); | |
| for (var i = 0; i < allDescriptors.length; ++i) { | |
| if (hiddenPanels.indexOf(allDescriptors[i].name()) === -1) | |
| panelDescriptors.push(allDescriptors[i]); | |
| } | |
| return panelDescriptors; | |
| }, | |
| _panelSelected: function() | |
| { | |
| this._toggleConsoleButton.disabled = WebInspector.inspectorView.currentPanel().name === "console"; | |
| }, | |
| _createGlobalStatusBarItems: function() | |
| { | |
| var bottomStatusBarContainer = document.getElementById("bottom-status-bar-container"); | |
| this._dockToggleButton = new WebInspector.StatusBarButton("", "dock-status-bar-item", 3); | |
| this._dockToggleButton.makeLongClickEnabled(this._createDockOptions.bind(this)); | |
| this._dockToggleButton.addEventListener("click", this._toggleAttach.bind(this), false); | |
| this._updateDockButtonState(); | |
| var mainStatusBar = document.getElementById("main-status-bar"); | |
| mainStatusBar.insertBefore(this._dockToggleButton.element, bottomStatusBarContainer); | |
| this._toggleConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Show console."), "console-status-bar-item"); | |
| this._toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false); | |
| mainStatusBar.insertBefore(this._toggleConsoleButton.element, bottomStatusBarContainer); | |
| if (!WebInspector.WorkerManager.isWorkerFrontend()) { | |
| this._nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item"); | |
| this._nodeSearchButton.addEventListener("click", this.toggleSearchingForNode, this); | |
| mainStatusBar.insertBefore(this._nodeSearchButton.element, bottomStatusBarContainer); | |
| } | |
| mainStatusBar.appendChild(this.settingsController.statusBarItem); | |
| }, | |
| _createDockOptions: function() | |
| { | |
| var alternateDockToggleButton1 = new WebInspector.StatusBarButton("Dock to main window.", "dock-status-bar-item", 3); | |
| var alternateDockToggleButton2 = new WebInspector.StatusBarButton("Undock into separate window.", "dock-status-bar-item", 3); | |
| if (this.attached) { | |
| alternateDockToggleButton1.state = WebInspector.settings.dockToRight.get() ? "bottom" : "right"; | |
| alternateDockToggleButton2.state = "undock"; | |
| } else { | |
| alternateDockToggleButton1.state = WebInspector.settings.dockToRight.get() ? "bottom" : "right"; | |
| alternateDockToggleButton2.state = WebInspector.settings.dockToRight.get() ? "right" : "bottom"; | |
| } | |
| alternateDockToggleButton1.addEventListener("click", onClick.bind(this), false); | |
| alternateDockToggleButton2.addEventListener("click", onClick.bind(this), false); | |
| function onClick(e) | |
| { | |
| var state = e.target.state; | |
| if (state === "undock") | |
| this._toggleAttach(); | |
| else if (state === "right") { | |
| if (!this.attached) | |
| this._toggleAttach(); | |
| WebInspector.settings.dockToRight.set(true); | |
| } else if (state === "bottom") { | |
| if (!this.attached) | |
| this._toggleAttach(); | |
| WebInspector.settings.dockToRight.set(false); | |
| } | |
| } | |
| return [alternateDockToggleButton1, alternateDockToggleButton2]; | |
| }, | |
| _updateDockButtonState: function() | |
| { | |
| if (!this._dockToggleButton) | |
| return; | |
| if (this.attached) { | |
| this._dockToggleButton.disabled = false; | |
| this._dockToggleButton.state = "undock"; | |
| this._dockToggleButton.title = WebInspector.UIString("Undock into separate window."); | |
| } else { | |
| this._dockToggleButton.disabled = this._isDockingUnavailable; | |
| this._dockToggleButton.state = WebInspector.settings.dockToRight.get() ? "right" : "bottom"; | |
| this._dockToggleButton.title = WebInspector.UIString("Dock to main window."); | |
| } | |
| }, | |
| _toggleAttach: function() | |
| { | |
| if (!this._attached) { | |
| InspectorFrontendHost.requestAttachWindow(); | |
| WebInspector.userMetrics.WindowDocked.record(); | |
| } else { | |
| InspectorFrontendHost.requestDetachWindow(); | |
| WebInspector.userMetrics.WindowUndocked.record(); | |
| } | |
| }, | |
| _toggleConsoleButtonClicked: function() | |
| { | |
| if (this._toggleConsoleButton.disabled) | |
| return; | |
| this._toggleConsoleButton.toggled = !this._toggleConsoleButton.toggled; | |
| var animationType = window.event && window.event.shiftKey ? WebInspector.Drawer.AnimationType.Slow : WebInspector.Drawer.AnimationType.Normal; | |
| if (this._toggleConsoleButton.toggled) { | |
| this._toggleConsoleButton.title = WebInspector.UIString("Hide console."); | |
| this.drawer.show(this.consoleView, animationType); | |
| this._consoleWasShown = true; | |
| } else { | |
| this._toggleConsoleButton.title = WebInspector.UIString("Show console."); | |
| this.drawer.hide(animationType); | |
| delete this._consoleWasShown; | |
| } | |
| }, | |
| showViewInDrawer: function(statusBarElement, view, onclose) | |
| { | |
| this._toggleConsoleButton.title = WebInspector.UIString("Hide console."); | |
| this._toggleConsoleButton.toggled = false; | |
| this._closePreviousDrawerView(); | |
| var drawerStatusBarHeader = document.createElement("div"); | |
| drawerStatusBarHeader.className = "drawer-header status-bar-item"; | |
| drawerStatusBarHeader.appendChild(statusBarElement); | |
| drawerStatusBarHeader.onclose = onclose; | |
| var closeButton = drawerStatusBarHeader.createChild("span"); | |
| closeButton.textContent = WebInspector.UIString("\u00D7"); | |
| closeButton.addStyleClass("drawer-header-close-button"); | |
| closeButton.addEventListener("click", this.closeViewInDrawer.bind(this), false); | |
| document.getElementById("panel-status-bar").firstElementChild.appendChild(drawerStatusBarHeader); | |
| this._drawerStatusBarHeader = drawerStatusBarHeader; | |
| this.drawer.show(view, WebInspector.Drawer.AnimationType.Immediately); | |
| }, | |
| closeViewInDrawer: function() | |
| { | |
| if (this._drawerStatusBarHeader) { | |
| this._closePreviousDrawerView(); | |
| if (!this._consoleWasShown) | |
| this.drawer.hide(WebInspector.Drawer.AnimationType.Immediately); | |
| else | |
| this._toggleConsoleButtonClicked(); | |
| } | |
| }, | |
| _closePreviousDrawerView: function() | |
| { | |
| if (this._drawerStatusBarHeader) { | |
| this._drawerStatusBarHeader.parentElement.removeChild(this._drawerStatusBarHeader); | |
| if (this._drawerStatusBarHeader.onclose) | |
| this._drawerStatusBarHeader.onclose(); | |
| delete this._drawerStatusBarHeader; | |
| } | |
| }, | |
| get attached() | |
| { | |
| return this._attached; | |
| }, | |
| set attached(x) | |
| { | |
| if (this._attached === x) | |
| return; | |
| this._attached = x; | |
| if (x) | |
| document.body.removeStyleClass("detached"); | |
| else | |
| document.body.addStyleClass("detached"); | |
| this._setCompactMode(x && !WebInspector.settings.dockToRight.get()); | |
| this._updateDockButtonState(); | |
| }, | |
| isCompactMode: function() | |
| { | |
| return this.attached && !WebInspector.settings.dockToRight.get(); | |
| }, | |
| _setCompactMode: function(x) | |
| { | |
| var body = document.body; | |
| if (x) | |
| body.addStyleClass("compact"); | |
| else | |
| body.removeStyleClass("compact"); | |
| WebInspector.windowResize(); | |
| }, | |
| _updateErrorAndWarningCounts: function() | |
| { | |
| var errorWarningElement = document.getElementById("error-warning-count"); | |
| if (!errorWarningElement) | |
| return; | |
| var errors = WebInspector.console.errors; | |
| var warnings = WebInspector.console.warnings; | |
| if (!errors && !warnings) { | |
| errorWarningElement.addStyleClass("hidden"); | |
| return; | |
| } | |
| errorWarningElement.removeStyleClass("hidden"); | |
| errorWarningElement.removeChildren(); | |
| if (errors) { | |
| var errorImageElement = document.createElement("img"); | |
| errorImageElement.id = "error-count-img"; | |
| errorWarningElement.appendChild(errorImageElement); | |
| var errorElement = document.createElement("span"); | |
| errorElement.id = "error-count"; | |
| errorElement.textContent = errors; | |
| errorWarningElement.appendChild(errorElement); | |
| } | |
| if (warnings) { | |
| var warningsImageElement = document.createElement("img"); | |
| warningsImageElement.id = "warning-count-img"; | |
| errorWarningElement.appendChild(warningsImageElement); | |
| var warningsElement = document.createElement("span"); | |
| warningsElement.id = "warning-count"; | |
| warningsElement.textContent = warnings; | |
| errorWarningElement.appendChild(warningsElement); | |
| } | |
| if (errors) { | |
| if (warnings) { | |
| if (errors == 1) { | |
| if (warnings == 1) | |
| errorWarningElement.title = WebInspector.UIString("%d error, %d warning", errors, warnings); | |
| else | |
| errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", errors, warnings); | |
| } else if (warnings == 1) | |
| errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", errors, warnings); | |
| else | |
| errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", errors, warnings); | |
| } else if (errors == 1) | |
| errorWarningElement.title = WebInspector.UIString("%d error", errors); | |
| else | |
| errorWarningElement.title = WebInspector.UIString("%d errors", errors); | |
| } else if (warnings == 1) | |
| errorWarningElement.title = WebInspector.UIString("%d warning", warnings); | |
| else if (warnings) | |
| errorWarningElement.title = WebInspector.UIString("%d warnings", warnings); | |
| else | |
| errorWarningElement.title = null; | |
| }, | |
| get inspectedPageDomain() | |
| { | |
| var parsedURL = WebInspector.inspectedPageURL && WebInspector.inspectedPageURL.asParsedURL(); | |
| return parsedURL ? parsedURL.host : ""; | |
| }, | |
| _initializeCapability: function(name, callback, error, result) | |
| { | |
| Capabilities[name] = result; | |
| if (callback) | |
| callback(); | |
| }, | |
| _zoomIn: function() | |
| { | |
| ++this._zoomLevel; | |
| this._requestZoom(); | |
| }, | |
| _zoomOut: function() | |
| { | |
| --this._zoomLevel; | |
| this._requestZoom(); | |
| }, | |
| _resetZoom: function() | |
| { | |
| this._zoomLevel = 0; | |
| this._requestZoom(); | |
| }, | |
| _requestZoom: function() | |
| { | |
| WebInspector.settings.zoomLevel.set(this._zoomLevel); | |
| InspectorFrontendHost.setZoomFactor(Math.pow(1.2, this._zoomLevel)); | |
| }, | |
| toggleSearchingForNode: function() | |
| { | |
| var enabled = !this._nodeSearchButton.toggled; | |
| function callback(error) | |
| { | |
| if (!error) | |
| this._nodeSearchButton.toggled = enabled; | |
| } | |
| WebInspector.domAgent.setInspectModeEnabled(enabled, callback.bind(this)); | |
| }, | |
| _profilesLinkifier: function(title) | |
| { | |
| var profileStringMatches = WebInspector.ProfileURLRegExp.exec(title); | |
| if (profileStringMatches) { | |
| var profilesPanel = WebInspector.panel("profiles"); | |
| title = WebInspector.ProfilesPanel._instance.displayTitleForProfileLink(profileStringMatches[2], profileStringMatches[1]); | |
| } | |
| return title; | |
| }, | |
| _debuggerPaused: function() | |
| { | |
| WebInspector.panel("scripts"); | |
| } | |
| } | |
| WebInspector.Events = { | |
| InspectorClosing: "InspectorClosing" | |
| } | |
| {(function parseQueryParameters() | |
| { | |
| WebInspector.queryParamsObject = {}; | |
| var queryParams = window.location.search; | |
| if (!queryParams) | |
| return; | |
| var params = queryParams.substring(1).split("&"); | |
| for (var i = 0; i < params.length; ++i) { | |
| var pair = params[i].split("="); | |
| WebInspector.queryParamsObject[pair[0]] = pair[1]; | |
| } | |
| })();} | |
| WebInspector.loaded = function() | |
| { | |
| InspectorBackend.loadFromJSONIfNeeded("../Inspector.json"); | |
| if (WebInspector.WorkerManager.isDedicatedWorkerFrontend()) { | |
| WebInspector.doLoadedDone(); | |
| return; | |
| } | |
| var ws; | |
| if ("ws" in WebInspector.queryParamsObject) | |
| ws = "ws://" + WebInspector.queryParamsObject.ws; | |
| else if ("page" in WebInspector.queryParamsObject) { | |
| var page = WebInspector.queryParamsObject.page; | |
| var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host; | |
| ws = "ws://" + host + "/devtools/page/" + page; | |
| } | |
| if (ws) { | |
| WebInspector.socket = new WebSocket(ws); | |
| WebInspector.socket.onmessage = function(message) { InspectorBackend.dispatch(message.data); } | |
| WebInspector.socket.onerror = function(error) { console.error(error); } | |
| WebInspector.socket.onopen = function() { | |
| InspectorFrontendHost.sendMessageToBackend = WebInspector.socket.send.bind(WebInspector.socket); | |
| WebInspector.doLoadedDone(); | |
| } | |
| return; | |
| } | |
| WebInspector.doLoadedDone(); | |
| if (InspectorFrontendHost.isStub) { | |
| InspectorFrontendAPI.dispatchQueryParameters(); | |
| WebInspector._doLoadedDoneWithCapabilities(); | |
| } | |
| } | |
| WebInspector.doLoadedDone = function() | |
| { | |
| WebInspector.installPortStyles(); | |
| if (WebInspector.socket) | |
| document.body.addStyleClass("remote"); | |
| if (WebInspector.queryParamsObject.toolbarColor && WebInspector.queryParamsObject.textColor) | |
| WebInspector.setToolbarColors(WebInspector.queryParamsObject.toolbarColor, WebInspector.queryParamsObject.textColor); | |
| InspectorFrontendHost.loaded(); | |
| WebInspector.WorkerManager.loaded(); | |
| DebuggerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "debuggerCausesRecompilation", null)); | |
| DebuggerAgent.supportsSeparateScriptCompilationAndExecution(WebInspector._initializeCapability.bind(WebInspector, "separateScriptCompilationAndExecutionEnabled", null)); | |
| ProfilerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "profilerCausesRecompilation", null)); | |
| ProfilerAgent.isSampling(WebInspector._initializeCapability.bind(WebInspector, "samplingCPUProfiler", null)); | |
| ProfilerAgent.hasHeapProfiler(WebInspector._initializeCapability.bind(WebInspector, "heapProfilerPresent", null)); | |
| TimelineAgent.supportsFrameInstrumentation(WebInspector._initializeCapability.bind(WebInspector, "timelineSupportsFrameInstrumentation", null)); | |
| PageAgent.canOverrideDeviceMetrics(WebInspector._initializeCapability.bind(WebInspector, "canOverrideDeviceMetrics", null)); | |
| PageAgent.canOverrideGeolocation(WebInspector._initializeCapability.bind(WebInspector, "canOverrideGeolocation", null)); | |
| PageAgent.canOverrideDeviceOrientation(WebInspector._initializeCapability.bind(WebInspector, "canOverrideDeviceOrientation", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector))); | |
| } | |
| WebInspector._doLoadedDoneWithCapabilities = function() | |
| { | |
| WebInspector.shortcutsScreen = new WebInspector.ShortcutsScreen(); | |
| this._registerShortcuts(); | |
| WebInspector.shortcutsScreen.section(WebInspector.UIString("Console")); | |
| WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel")); | |
| this.console = new WebInspector.ConsoleModel(); | |
| this.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._updateErrorAndWarningCounts, this); | |
| this.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._updateErrorAndWarningCounts, this); | |
| this.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._updateErrorAndWarningCounts, this); | |
| WebInspector.CSSCompletions.requestCSSNameCompletions(); | |
| this.drawer = new WebInspector.Drawer(); | |
| this.networkManager = new WebInspector.NetworkManager(); | |
| this.resourceTreeModel = new WebInspector.ResourceTreeModel(this.networkManager); | |
| this.debuggerModel = new WebInspector.DebuggerModel(); | |
| this.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); | |
| this.networkLog = new WebInspector.NetworkLog(); | |
| this.domAgent = new WebInspector.DOMAgent(); | |
| this.runtimeModel = new WebInspector.RuntimeModel(this.resourceTreeModel); | |
| this.consoleView = new WebInspector.ConsoleView(WebInspector.WorkerManager.isWorkerFrontend()); | |
| InspectorBackend.registerInspectorDispatcher(this); | |
| this.cssModel = new WebInspector.CSSStyleModel(); | |
| this.timelineManager = new WebInspector.TimelineManager(); | |
| this.userAgentSupport = new WebInspector.UserAgentSupport(); | |
| this.searchController = new WebInspector.SearchController(); | |
| this.advancedSearchController = new WebInspector.AdvancedSearchController(); | |
| this.settingsController = new WebInspector.SettingsController(); | |
| this.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane(); | |
| this._zoomLevel = WebInspector.settings.zoomLevel.get(); | |
| if (this._zoomLevel) | |
| this._requestZoom(); | |
| var autoselectPanel = WebInspector.UIString("a panel chosen automatically"); | |
| var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel); | |
| this.openAnchorLocationRegistry = new WebInspector.HandlerRegistry(openAnchorLocationSetting); | |
| this.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; }); | |
| this.workspace = new WebInspector.Workspace(); | |
| this.workspaceController = new WebInspector.WorkspaceController(this.workspace); | |
| this.breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, this.debuggerModel, this.workspace); | |
| this.scriptSnippetModel = new WebInspector.ScriptSnippetModel(this.workspace); | |
| new WebInspector.DebuggerScriptMapping(this.workspace); | |
| new WebInspector.NetworkUISourceCodeProvider(this.workspace); | |
| new WebInspector.StylesSourceMapping(this.workspace); | |
| if (WebInspector.experimentsSettings.sass.isEnabled()) | |
| new WebInspector.SASSSourceMapping(this.workspace); | |
| new WebInspector.PresentationConsoleMessageHelper(this.workspace); | |
| this._createGlobalStatusBarItems(); | |
| WebInspector._installDockToRight(); | |
| this.toolbar = new WebInspector.Toolbar(); | |
| WebInspector.startBatchUpdate(); | |
| var panelDescriptors = this._panelDescriptors(); | |
| for (var i = 0; i < panelDescriptors.length; ++i) | |
| WebInspector.inspectorView.addPanel(panelDescriptors[i]); | |
| WebInspector.endBatchUpdate(); | |
| this.addMainEventListeners(document); | |
| WebInspector.registerLinkifierPlugin(this._profilesLinkifier.bind(this)); | |
| window.addEventListener("resize", this.windowResize.bind(this), true); | |
| var errorWarningCount = document.getElementById("error-warning-count"); | |
| errorWarningCount.addEventListener("click", this.showConsole.bind(this), false); | |
| this._updateErrorAndWarningCounts(); | |
| this.extensionServer.initExtensions(); | |
| this.console.enableAgent(); | |
| function showInitialPanel() | |
| { | |
| if (!WebInspector.inspectorView.currentPanel()) | |
| WebInspector.showPanel(WebInspector.settings.lastActivePanel.get()); | |
| } | |
| InspectorAgent.enable(showInitialPanel); | |
| this.databaseModel = new WebInspector.DatabaseModel(); | |
| this.domStorageModel = new WebInspector.DOMStorageModel(); | |
| if (!Capabilities.profilerCausesRecompilation || WebInspector.settings.profilerEnabled.get()) | |
| ProfilerAgent.enable(); | |
| if (WebInspector.settings.showPaintRects.get()) | |
| PageAgent.setShowPaintRects(true); | |
| if (WebInspector.settings.javaScriptDisabled.get()) | |
| PageAgent.setScriptExecutionDisabled(true); | |
| this.domAgent._emulateTouchEventsChanged(); | |
| WebInspector.WorkerManager.loadCompleted(); | |
| InspectorFrontendAPI.loadCompleted(); | |
| } | |
| WebInspector._installDockToRight = function() | |
| { | |
| WebInspector.settings.dockToRight.set(WebInspector.queryParamsObject.dockSide === "right"); | |
| if (WebInspector.settings.dockToRight.get()) | |
| document.body.addStyleClass("dock-to-right"); | |
| if (WebInspector.attached) | |
| WebInspector._setCompactMode(!WebInspector.settings.dockToRight.get()); | |
| WebInspector.settings.dockToRight.addChangeListener(listener.bind(this)); | |
| function listener(event) | |
| { | |
| var value = WebInspector.settings.dockToRight.get(); | |
| if (value) { | |
| InspectorFrontendHost.requestSetDockSide("right"); | |
| document.body.addStyleClass("dock-to-right"); | |
| } else { | |
| InspectorFrontendHost.requestSetDockSide("bottom"); | |
| document.body.removeStyleClass("dock-to-right"); | |
| } | |
| if (WebInspector.attached) | |
| WebInspector._setCompactMode(!value); | |
| else | |
| WebInspector._updateDockButtonState(); | |
| } | |
| } | |
| var windowLoaded = function() | |
| { | |
| var localizedStringsURL = InspectorFrontendHost.localizedStringsURL(); | |
| if (localizedStringsURL) { | |
| var localizedStringsScriptElement = document.createElement("script"); | |
| localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false); | |
| localizedStringsScriptElement.type = "text/javascript"; | |
| localizedStringsScriptElement.src = localizedStringsURL; | |
| document.head.appendChild(localizedStringsScriptElement); | |
| } else | |
| WebInspector.loaded(); | |
| WebInspector.attached = WebInspector.queryParamsObject.docked === "true"; | |
| window.removeEventListener("DOMContentLoaded", windowLoaded, false); | |
| delete windowLoaded; | |
| }; | |
| window.addEventListener("DOMContentLoaded", windowLoaded, false); | |
| var messagesToDispatch = []; | |
| WebInspector.dispatchQueueIsEmpty = function() { | |
| return messagesToDispatch.length == 0; | |
| } | |
| WebInspector.dispatch = function(message) { | |
| messagesToDispatch.push(message); | |
| setTimeout(function() { | |
| InspectorBackend.dispatch(messagesToDispatch.shift()); | |
| }, 0); | |
| } | |
| WebInspector.dispatchMessageFromBackend = function(messageObject) | |
| { | |
| WebInspector.dispatch(messageObject); | |
| } | |
| WebInspector.windowResize = function(event) | |
| { | |
| if (WebInspector.inspectorView) | |
| WebInspector.inspectorView.doResize(); | |
| if (WebInspector.drawer) | |
| WebInspector.drawer.resize(); | |
| if (WebInspector.toolbar) | |
| WebInspector.toolbar.resize(); | |
| if (WebInspector.settingsController) | |
| WebInspector.settingsController.resize(); | |
| } | |
| WebInspector.setDockingUnavailable = function(unavailable) | |
| { | |
| this._isDockingUnavailable = unavailable; | |
| this._updateDockButtonState(); | |
| } | |
| WebInspector.close = function(event) | |
| { | |
| if (this._isClosing) | |
| return; | |
| this._isClosing = true; | |
| this.notifications.dispatchEventToListeners(WebInspector.Events.InspectorClosing); | |
| InspectorFrontendHost.closeWindow(); | |
| } | |
| WebInspector.documentClick = function(event) | |
| { | |
| var anchor = event.target.enclosingNodeOrSelfWithNodeName("a"); | |
| if (!anchor || anchor.target === "_blank") | |
| return; | |
| event.consume(true); | |
| function followLink() | |
| { | |
| if (WebInspector.isBeingEdited(event.target) || WebInspector._showAnchorLocation(anchor)) | |
| return; | |
| const profileMatch = WebInspector.ProfileURLRegExp.exec(anchor.href); | |
| if (profileMatch) { | |
| WebInspector.showProfileForURL(anchor.href); | |
| return; | |
| } | |
| var parsedURL = anchor.href.asParsedURL(); | |
| if (parsedURL && parsedURL.scheme === "webkit-link-action") { | |
| if (parsedURL.host === "show-panel") { | |
| var panel = parsedURL.path.substring(1); | |
| if (WebInspector.panel(panel)) | |
| WebInspector.showPanel(panel); | |
| } | |
| return; | |
| } | |
| InspectorFrontendHost.openInNewTab(anchor.href); | |
| } | |
| if (WebInspector.followLinkTimeout) | |
| clearTimeout(WebInspector.followLinkTimeout); | |
| if (anchor.preventFollowOnDoubleClick) { | |
| if (event.detail === 1) | |
| WebInspector.followLinkTimeout = setTimeout(followLink, 333); | |
| return; | |
| } | |
| followLink(); | |
| } | |
| WebInspector.openResource = function(resourceURL, inResourcesPanel) | |
| { | |
| var resource = WebInspector.resourceForURL(resourceURL); | |
| if (inResourcesPanel && resource) | |
| WebInspector.showPanel("resources").showResource(resource); | |
| else | |
| InspectorFrontendHost.openInNewTab(resourceURL); | |
| } | |
| WebInspector._registerShortcuts = function() | |
| { | |
| var shortcut = WebInspector.KeyboardShortcut; | |
| var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("All Panels")); | |
| var keys = [ | |
| shortcut.shortcutToString("]", shortcut.Modifiers.CtrlOrMeta), | |
| shortcut.shortcutToString("[", shortcut.Modifiers.CtrlOrMeta) | |
| ]; | |
| section.addRelatedKeys(keys, WebInspector.UIString("Go to the panel to the left/right")); | |
| var keys = [ | |
| shortcut.shortcutToString("[", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt), | |
| shortcut.shortcutToString("]", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt) | |
| ]; | |
| section.addRelatedKeys(keys, WebInspector.UIString("Go back/forward in panel history")); | |
| section.addKey(shortcut.shortcutToString(shortcut.Keys.Esc), WebInspector.UIString("Toggle console")); | |
| section.addKey(shortcut.shortcutToString("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search")); | |
| var advancedSearchShortcut = WebInspector.AdvancedSearchController.createShortcut(); | |
| section.addKey(advancedSearchShortcut.name, WebInspector.UIString("Search across all sources")); | |
| var openResourceShortcut = WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta); | |
| section.addKey(openResourceShortcut.name, WebInspector.UIString("Go to source")); | |
| if (WebInspector.isMac()) { | |
| keys = [ | |
| shortcut.shortcutToString("g", shortcut.Modifiers.Meta), | |
| shortcut.shortcutToString("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift) | |
| ]; | |
| section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous")); | |
| } | |
| var goToShortcut = WebInspector.GoToLineDialog.createShortcut(); | |
| section.addKey(goToShortcut.name, WebInspector.UIString("Go to line")); | |
| } | |
| WebInspector.documentKeyDown = function(event) | |
| { | |
| const helpKey = WebInspector.isMac() ? "U+003F" : "U+00BF"; | |
| if (event.keyIdentifier === "F1" || | |
| (event.keyIdentifier === helpKey && event.shiftKey && (!WebInspector.isBeingEdited(event.target) || event.metaKey))) { | |
| this.settingsController.showSettingsScreen(WebInspector.SettingsScreen.Tabs.Shortcuts); | |
| event.consume(true); | |
| return; | |
| } | |
| if (WebInspector.currentFocusElement() && WebInspector.currentFocusElement().handleKeyEvent) { | |
| WebInspector.currentFocusElement().handleKeyEvent(event); | |
| if (event.handled) { | |
| event.consume(true); | |
| return; | |
| } | |
| } | |
| if (WebInspector.inspectorView.currentPanel()) { | |
| WebInspector.inspectorView.currentPanel().handleShortcut(event); | |
| if (event.handled) { | |
| event.consume(true); | |
| return; | |
| } | |
| } | |
| if (WebInspector.searchController.handleShortcut(event)) | |
| return; | |
| if (WebInspector.advancedSearchController.handleShortcut(event)) | |
| return; | |
| switch (event.keyIdentifier) { | |
| case "U+004F": | |
| if (!event.shiftKey && !event.altKey && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)) { | |
| WebInspector.showPanel("scripts").showGoToSourceDialog(); | |
| event.consume(true); | |
| } | |
| break; | |
| case "U+0052": | |
| if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)) { | |
| PageAgent.reload(event.shiftKey); | |
| event.consume(true); | |
| } | |
| break; | |
| case "F5": | |
| if (!WebInspector.isMac()) { | |
| PageAgent.reload(event.ctrlKey || event.shiftKey); | |
| event.consume(true); | |
| } | |
| break; | |
| } | |
| var isValidZoomShortcut = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && | |
| !event.altKey && | |
| !InspectorFrontendHost.isStub; | |
| switch (event.keyCode) { | |
| case 107: | |
| case 187: | |
| if (isValidZoomShortcut) { | |
| WebInspector._zoomIn(); | |
| event.consume(true); | |
| } | |
| break; | |
| case 109: | |
| case 189: | |
| if (isValidZoomShortcut) { | |
| WebInspector._zoomOut(); | |
| event.consume(true); | |
| } | |
| break; | |
| case 48: | |
| if (isValidZoomShortcut && !event.shiftKey) { | |
| WebInspector._resetZoom(); | |
| event.consume(true); | |
| } | |
| break; | |
| } | |
| if (event.keyIdentifier === "U+0043") { | |
| if (WebInspector.isMac()) | |
| var isNodeSearchKey = event.metaKey && !event.ctrlKey && !event.altKey && event.shiftKey; | |
| else | |
| var isNodeSearchKey = event.ctrlKey && !event.metaKey && !event.altKey && event.shiftKey; | |
| if (isNodeSearchKey) { | |
| this.toggleSearchingForNode(); | |
| event.consume(true); | |
| return; | |
| } | |
| return; | |
| } | |
| } | |
| WebInspector.postDocumentKeyDown = function(event) | |
| { | |
| if (event.handled) | |
| return; | |
| if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) { | |
| if (!this._toggleConsoleButton.toggled && WebInspector.drawer.visible) | |
| this.closeViewInDrawer(); | |
| else | |
| this._toggleConsoleButtonClicked(); | |
| } | |
| } | |
| WebInspector.documentCanCopy = function(event) | |
| { | |
| if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().handleCopyEvent) | |
| event.preventDefault(); | |
| } | |
| WebInspector.documentCopy = function(event) | |
| { | |
| if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().handleCopyEvent) | |
| WebInspector.inspectorView.currentPanel().handleCopyEvent(event); | |
| WebInspector.documentCopyEventFired(event); | |
| } | |
| WebInspector.documentCopyEventFired = function(event) | |
| { | |
| } | |
| WebInspector.contextMenuEventFired = function(event) | |
| { | |
| if (event.handled || event.target.hasStyleClass("popup-glasspane")) | |
| event.preventDefault(); | |
| } | |
| WebInspector.showConsole = function() | |
| { | |
| if (WebInspector._toggleConsoleButton && !WebInspector._toggleConsoleButton.toggled) { | |
| if (WebInspector.drawer.visible) | |
| this._closePreviousDrawerView(); | |
| WebInspector._toggleConsoleButtonClicked(); | |
| } | |
| } | |
| WebInspector.showPanel = function(panel) | |
| { | |
| return WebInspector.inspectorView.showPanel(panel); | |
| } | |
| WebInspector.panel = function(panel) | |
| { | |
| return WebInspector.inspectorView.panel(panel); | |
| } | |
| WebInspector.bringToFront = function() | |
| { | |
| InspectorFrontendHost.bringToFront(); | |
| } | |
| WebInspector.log = function(message, messageLevel, showConsole) | |
| { | |
| var self = this; | |
| function isLogAvailable() | |
| { | |
| return WebInspector.ConsoleMessage && WebInspector.RemoteObject && self.console; | |
| } | |
| function flushQueue() | |
| { | |
| var queued = WebInspector.log.queued; | |
| if (!queued) | |
| return; | |
| for (var i = 0; i < queued.length; ++i) | |
| logMessage(queued[i]); | |
| delete WebInspector.log.queued; | |
| } | |
| function flushQueueIfAvailable() | |
| { | |
| if (!isLogAvailable()) | |
| return; | |
| clearInterval(WebInspector.log.interval); | |
| delete WebInspector.log.interval; | |
| flushQueue(); | |
| } | |
| function logMessage(message) | |
| { | |
| var msg = WebInspector.ConsoleMessage.create( | |
| WebInspector.ConsoleMessage.MessageSource.Other, | |
| messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug, | |
| message); | |
| self.console.addMessage(msg); | |
| if (showConsole) | |
| WebInspector.showConsole(); | |
| } | |
| if (!isLogAvailable()) { | |
| if (!WebInspector.log.queued) | |
| WebInspector.log.queued = []; | |
| WebInspector.log.queued.push(message); | |
| if (!WebInspector.log.interval) | |
| WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000); | |
| return; | |
| } | |
| flushQueue(); | |
| logMessage(message); | |
| } | |
| WebInspector.showErrorMessage = function(error) | |
| { | |
| WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true); | |
| } | |
| WebInspector.inspect = function(payload, hints) | |
| { | |
| var object = WebInspector.RemoteObject.fromPayload(payload); | |
| if (object.subtype === "node") { | |
| function callback(nodeId) | |
| { | |
| WebInspector._updateFocusedNode(nodeId); | |
| object.release(); | |
| } | |
| object.pushNodeToFrontend(callback); | |
| return; | |
| } | |
| if (hints.databaseId) | |
| WebInspector.showPanel("resources").selectDatabase(WebInspector.databaseModel.databaseForId(hints.databaseId)); | |
| else if (hints.domStorageId) | |
| WebInspector.showPanel("resources").selectDOMStorage(WebInspector.domStorageModel.storageForId(hints.domStorageId)); | |
| object.release(); | |
| } | |
| WebInspector._updateFocusedNode = function(nodeId) | |
| { | |
| if (WebInspector._nodeSearchButton.toggled) { | |
| InspectorFrontendHost.bringToFront(); | |
| WebInspector._nodeSearchButton.toggled = false; | |
| } | |
| WebInspector.showPanel("elements").revealAndSelectNode(nodeId); | |
| } | |
| WebInspector._showAnchorLocation = function(anchor) | |
| { | |
| if (WebInspector.openAnchorLocationRegistry.dispatch({ url: anchor.href, lineNumber: anchor.lineNumber})) | |
| return true; | |
| var preferredPanel = this.panels[anchor.preferredPanel]; | |
| if (preferredPanel && WebInspector._showAnchorLocationInPanel(anchor, preferredPanel)) | |
| return true; | |
| if (WebInspector._showAnchorLocationInPanel(anchor, this.panel("scripts"))) | |
| return true; | |
| if (WebInspector._showAnchorLocationInPanel(anchor, this.panel("resources"))) | |
| return true; | |
| if (WebInspector._showAnchorLocationInPanel(anchor, this.panel("network"))) | |
| return true; | |
| return false; | |
| } | |
| WebInspector._showAnchorLocationInPanel = function(anchor, panel) | |
| { | |
| if (!panel || !panel.canShowAnchorLocation(anchor)) | |
| return false; | |
| if (anchor.hasStyleClass("webkit-html-external-link")) { | |
| anchor.removeStyleClass("webkit-html-external-link"); | |
| anchor.addStyleClass("webkit-html-resource-link"); | |
| } | |
| WebInspector.inspectorView.showPanelForAnchorNavigation(panel); | |
| panel.showAnchorLocation(anchor); | |
| return true; | |
| } | |
| WebInspector.showProfileForURL = function(url) | |
| { | |
| WebInspector.showPanel("profiles").showProfileForURL(url); | |
| } | |
| WebInspector.evaluateInConsole = function(expression, showResultOnly) | |
| { | |
| this.showConsole(); | |
| this.consoleView.evaluateUsingTextPrompt(expression, showResultOnly); | |
| } | |
| WebInspector.addMainEventListeners = function(doc) | |
| { | |
| doc.addEventListener("keydown", this.documentKeyDown.bind(this), true); | |
| doc.addEventListener("keydown", this.postDocumentKeyDown.bind(this), false); | |
| doc.addEventListener("beforecopy", this.documentCanCopy.bind(this), true); | |
| doc.addEventListener("copy", this.documentCopy.bind(this), true); | |
| doc.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true); | |
| doc.addEventListener("click", this.documentClick.bind(this), true); | |
| } | |
| WebInspector.ProfileURLRegExp = /webkit-profile:\/\/(.+)\/(.+)#([0-9]+)/; | |
| WebInspector.UIString = function(string, vararg) | |
| { | |
| if (Preferences.localizeUI) { | |
| if (window.localizedStrings && string in window.localizedStrings) | |
| string = window.localizedStrings[string]; | |
| else { | |
| if (!(string in WebInspector._missingLocalizedStrings)) { | |
| console.warn("Localized string \"" + string + "\" not found."); | |
| WebInspector._missingLocalizedStrings[string] = true; | |
| } | |
| if (Preferences.showMissingLocalizedStrings) | |
| string += " (not localized)"; | |
| } | |
| } | |
| return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); | |
| } | |
| WebInspector._missingLocalizedStrings = {}; | |
| WebInspector.installDragHandle = function(element, elementDragStart, elementDrag, elementDragEnd, cursor) | |
| { | |
| element.addEventListener("mousedown", WebInspector._elementDragStart.bind(WebInspector, elementDragStart, elementDrag, elementDragEnd, cursor), false); | |
| } | |
| WebInspector._elementDragStart = function(elementDragStart, elementDrag, elementDragEnd, cursor, event) | |
| { | |
| if (event.button || (WebInspector.isMac() && event.ctrlKey)) | |
| return; | |
| if (WebInspector._elementDraggingEventListener) | |
| return; | |
| if (elementDragStart && !elementDragStart(event)) | |
| return; | |
| if (WebInspector._elementDraggingGlassPane) { | |
| WebInspector._elementDraggingGlassPane.dispose(); | |
| delete WebInspector._elementDraggingGlassPane; | |
| } | |
| var targetDocument = event.target.ownerDocument; | |
| WebInspector._elementDraggingEventListener = elementDrag; | |
| WebInspector._elementEndDraggingEventListener = elementDragEnd; | |
| WebInspector._mouseOutWhileDraggingTargetDocument = targetDocument; | |
| targetDocument.addEventListener("mousemove", WebInspector._elementDraggingEventListener, true); | |
| targetDocument.addEventListener("mouseup", WebInspector._elementDragEnd, true); | |
| targetDocument.addEventListener("mouseout", WebInspector._mouseOutWhileDragging, true); | |
| targetDocument.body.style.cursor = cursor; | |
| event.preventDefault(); | |
| } | |
| WebInspector._mouseOutWhileDragging = function() | |
| { | |
| WebInspector._unregisterMouseOutWhileDragging(); | |
| WebInspector._elementDraggingGlassPane = new WebInspector.GlassPane(); | |
| } | |
| WebInspector._unregisterMouseOutWhileDragging = function() | |
| { | |
| if (!WebInspector._mouseOutWhileDraggingTargetDocument) | |
| return; | |
| WebInspector._mouseOutWhileDraggingTargetDocument.removeEventListener("mouseout", WebInspector._mouseOutWhileDragging, true); | |
| delete WebInspector._mouseOutWhileDraggingTargetDocument; | |
| } | |
| WebInspector._elementDragEnd = function(event) | |
| { | |
| var targetDocument = event.target.ownerDocument; | |
| targetDocument.removeEventListener("mousemove", WebInspector._elementDraggingEventListener, true); | |
| targetDocument.removeEventListener("mouseup", WebInspector._elementDragEnd, true); | |
| WebInspector._unregisterMouseOutWhileDragging(); | |
| targetDocument.body.style.removeProperty("cursor"); | |
| if (WebInspector._elementDraggingGlassPane) | |
| WebInspector._elementDraggingGlassPane.dispose(); | |
| var elementDragEnd = WebInspector._elementEndDraggingEventListener; | |
| delete WebInspector._elementDraggingGlassPane; | |
| delete WebInspector._elementDraggingEventListener; | |
| delete WebInspector._elementEndDraggingEventListener; | |
| event.preventDefault(); | |
| if (elementDragEnd) | |
| elementDragEnd(event); | |
| } | |
| WebInspector.GlassPane = function() | |
| { | |
| this.element = document.createElement("div"); | |
| this.element.style.cssText = "position:absolute;top:0;bottom:0;left:0;right:0;background-color:transparent;z-index:1000;"; | |
| this.element.id = "glass-pane-for-drag"; | |
| document.body.appendChild(this.element); | |
| } | |
| WebInspector.GlassPane.prototype = { | |
| dispose: function() | |
| { | |
| if (this.element.parentElement) | |
| this.element.parentElement.removeChild(this.element); | |
| } | |
| } | |
| WebInspector.animateStyle = function(animations, duration, callback) | |
| { | |
| var interval; | |
| var complete = 0; | |
| var hasCompleted = false; | |
| const intervalDuration = (1000 / 30); | |
| const animationsLength = animations.length; | |
| const propertyUnit = {opacity: ""}; | |
| const defaultUnit = "px"; | |
| function cubicInOut(t, b, c, d) | |
| { | |
| if ((t/=d/2) < 1) return c/2*t*t*t + b; | |
| return c/2*((t-=2)*t*t + 2) + b; | |
| } | |
| for (var i = 0; i < animationsLength; ++i) { | |
| var animation = animations[i]; | |
| var element = null, start = null, end = null, key = null; | |
| for (key in animation) { | |
| if (key === "element") | |
| element = animation[key]; | |
| else if (key === "start") | |
| start = animation[key]; | |
| else if (key === "end") | |
| end = animation[key]; | |
| } | |
| if (!element || !end) | |
| continue; | |
| if (!start) { | |
| var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element); | |
| start = {}; | |
| for (key in end) | |
| start[key] = parseInt(computedStyle.getPropertyValue(key), 10); | |
| animation.start = start; | |
| } else | |
| for (key in start) | |
| element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); | |
| } | |
| function animateLoop() | |
| { | |
| if (hasCompleted) | |
| return; | |
| complete += intervalDuration; | |
| var next = complete + intervalDuration; | |
| for (var i = 0; i < animationsLength; ++i) { | |
| var animation = animations[i]; | |
| var element = animation.element; | |
| var start = animation.start; | |
| var end = animation.end; | |
| if (!element || !end) | |
| continue; | |
| var style = element.style; | |
| for (key in end) { | |
| var endValue = end[key]; | |
| if (next < duration) { | |
| var startValue = start[key]; | |
| var newValue = cubicInOut(complete, startValue, endValue - startValue, duration); | |
| style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); | |
| } else | |
| style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); | |
| } | |
| } | |
| if (complete >= duration) { | |
| hasCompleted = true; | |
| clearInterval(interval); | |
| if (callback) | |
| callback(); | |
| } | |
| } | |
| function forceComplete() | |
| { | |
| if (hasCompleted) | |
| return; | |
| complete = duration; | |
| animateLoop(); | |
| } | |
| function cancel() | |
| { | |
| hasCompleted = true; | |
| clearInterval(interval); | |
| } | |
| interval = setInterval(animateLoop, intervalDuration); | |
| return { | |
| cancel: cancel, | |
| forceComplete: forceComplete | |
| }; | |
| } | |
| WebInspector.isBeingEdited = function(element) | |
| { | |
| if (element.hasStyleClass("text-prompt") || element.nodeName === "INPUT") | |
| return true; | |
| if (!WebInspector.__editingCount) | |
| return false; | |
| while (element) { | |
| if (element.__editing) | |
| return true; | |
| element = element.parentElement; | |
| } | |
| return false; | |
| } | |
| WebInspector.markBeingEdited = function(element, value) | |
| { | |
| if (value) { | |
| if (element.__editing) | |
| return false; | |
| element.__editing = true; | |
| WebInspector.__editingCount = (WebInspector.__editingCount || 0) + 1; | |
| } else { | |
| if (!element.__editing) | |
| return false; | |
| delete element.__editing; | |
| --WebInspector.__editingCount; | |
| } | |
| return true; | |
| } | |
| WebInspector.EditingConfig = function(commitHandler, cancelHandler, context) | |
| { | |
| this.commitHandler = commitHandler; | |
| this.cancelHandler = cancelHandler | |
| this.context = context; | |
| this.pasteHandler; | |
| this.multiline; | |
| this.customFinishHandler; | |
| } | |
| WebInspector.EditingConfig.prototype = { | |
| setPasteHandler: function(pasteHandler) | |
| { | |
| this.pasteHandler = pasteHandler; | |
| }, | |
| setMultiline: function(multiline) | |
| { | |
| this.multiline = multiline; | |
| }, | |
| setCustomFinishHandler: function(customFinishHandler) | |
| { | |
| this.customFinishHandler = customFinishHandler; | |
| } | |
| } | |
| WebInspector.CSSNumberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/; | |
| WebInspector.StyleValueDelimiters = " \xA0\t\n\"':;,/()"; | |
| WebInspector._valueModificationDirection = function(event) | |
| { | |
| var direction = null; | |
| if (event.type === "mousewheel") { | |
| if (event.wheelDeltaY > 0) | |
| direction = "Up"; | |
| else if (event.wheelDeltaY < 0) | |
| direction = "Down"; | |
| } else { | |
| if (event.keyIdentifier === "Up" || event.keyIdentifier === "PageUp") | |
| direction = "Up"; | |
| else if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown") | |
| direction = "Down"; | |
| } | |
| return direction; | |
| } | |
| WebInspector._modifiedHexValue = function(hexString, event) | |
| { | |
| var direction = WebInspector._valueModificationDirection(event); | |
| if (!direction) | |
| return hexString; | |
| var number = parseInt(hexString, 16); | |
| if (isNaN(number) || !isFinite(number)) | |
| return hexString; | |
| var maxValue = Math.pow(16, hexString.length) - 1; | |
| var arrowKeyOrMouseWheelEvent = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down" || event.type === "mousewheel"); | |
| var delta; | |
| if (arrowKeyOrMouseWheelEvent) | |
| delta = (direction === "Up") ? 1 : -1; | |
| else | |
| delta = (event.keyIdentifier === "PageUp") ? 16 : -16; | |
| if (event.shiftKey) | |
| delta *= 16; | |
| var result = number + delta; | |
| if (result < 0) | |
| result = 0; | |
| else if (result > maxValue) | |
| return hexString; | |
| var resultString = result.toString(16).toUpperCase(); | |
| for (var i = 0, lengthDelta = hexString.length - resultString.length; i < lengthDelta; ++i) | |
| resultString = "0" + resultString; | |
| return resultString; | |
| } | |
| WebInspector._modifiedFloatNumber = function(number, event) | |
| { | |
| var direction = WebInspector._valueModificationDirection(event); | |
| if (!direction) | |
| return number; | |
| var arrowKeyOrMouseWheelEvent = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down" || event.type === "mousewheel"); | |
| var changeAmount = 1; | |
| if (event.shiftKey && !arrowKeyOrMouseWheelEvent) | |
| changeAmount = 100; | |
| else if (event.shiftKey || !arrowKeyOrMouseWheelEvent) | |
| changeAmount = 10; | |
| else if (event.altKey) | |
| changeAmount = 0.1; | |
| if (direction === "Down") | |
| changeAmount *= -1; | |
| var result = Number((number + changeAmount).toFixed(6)); | |
| if (!String(result).match(WebInspector.CSSNumberRegex)) | |
| return null; | |
| return result; | |
| } | |
| WebInspector.handleElementValueModifications = function(event, element, finishHandler, suggestionHandler, customNumberHandler) | |
| { | |
| var arrowKeyOrMouseWheelEvent = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down" || event.type === "mousewheel"); | |
| var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown"); | |
| if (!arrowKeyOrMouseWheelEvent && !pageKeyPressed) | |
| return false; | |
| var selection = window.getSelection(); | |
| if (!selection.rangeCount) | |
| return false; | |
| var selectionRange = selection.getRangeAt(0); | |
| if (!selectionRange.commonAncestorContainer.isSelfOrDescendant(element)) | |
| return false; | |
| var originalValue = element.textContent; | |
| var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StyleValueDelimiters, element); | |
| var wordString = wordRange.toString(); | |
| if (suggestionHandler && suggestionHandler(wordString)) | |
| return false; | |
| var replacementString; | |
| var prefix, suffix, number; | |
| var matches; | |
| matches = /(.*#)([\da-fA-F]+)(.*)/.exec(wordString); | |
| if (matches && matches.length) { | |
| prefix = matches[1]; | |
| suffix = matches[3]; | |
| number = WebInspector._modifiedHexValue(matches[2], event); | |
| if (customNumberHandler) | |
| number = customNumberHandler(number); | |
| replacementString = prefix + number + suffix; | |
| } else { | |
| matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString); | |
| if (matches && matches.length) { | |
| prefix = matches[1]; | |
| suffix = matches[3]; | |
| number = WebInspector._modifiedFloatNumber(parseFloat(matches[2]), event); | |
| if (number === null) | |
| return false; | |
| if (customNumberHandler) | |
| number = customNumberHandler(number); | |
| replacementString = prefix + number + suffix; | |
| } | |
| } | |
| if (replacementString) { | |
| var replacementTextNode = document.createTextNode(replacementString); | |
| wordRange.deleteContents(); | |
| wordRange.insertNode(replacementTextNode); | |
| var finalSelectionRange = document.createRange(); | |
| finalSelectionRange.setStart(replacementTextNode, 0); | |
| finalSelectionRange.setEnd(replacementTextNode, replacementString.length); | |
| selection.removeAllRanges(); | |
| selection.addRange(finalSelectionRange); | |
| event.handled = true; | |
| event.preventDefault(); | |
| if (finishHandler) | |
| finishHandler(originalValue, replacementString); | |
| return true; | |
| } | |
| return false; | |
| } | |
| WebInspector.startEditing = function(element, config) | |
| { | |
| if (!WebInspector.markBeingEdited(element, true)) | |
| return null; | |
| config = config || new WebInspector.EditingConfig(function() {}, function() {}); | |
| var committedCallback = config.commitHandler; | |
| var cancelledCallback = config.cancelHandler; | |
| var pasteCallback = config.pasteHandler; | |
| var context = config.context; | |
| var oldText = getContent(element); | |
| var moveDirection = ""; | |
| element.addStyleClass("editing"); | |
| var oldTabIndex = element.getAttribute("tabIndex"); | |
| if (typeof oldTabIndex !== "number" || oldTabIndex < 0) | |
| element.tabIndex = 0; | |
| function blurEventListener() { | |
| editingCommitted.call(element); | |
| } | |
| function getContent(element) { | |
| if (element.tagName === "INPUT" && element.type === "text") | |
| return element.value; | |
| else | |
| return element.textContent; | |
| } | |
| function cleanUpAfterEditing() | |
| { | |
| WebInspector.markBeingEdited(element, false); | |
| this.removeStyleClass("editing"); | |
| if (typeof oldTabIndex !== "number") | |
| element.removeAttribute("tabIndex"); | |
| else | |
| this.tabIndex = oldTabIndex; | |
| this.scrollTop = 0; | |
| this.scrollLeft = 0; | |
| element.removeEventListener("blur", blurEventListener, false); | |
| element.removeEventListener("keydown", keyDownEventListener, true); | |
| if (pasteCallback) | |
| element.removeEventListener("paste", pasteEventListener, true); | |
| WebInspector.restoreFocusFromElement(element); | |
| } | |
| function editingCancelled() | |
| { | |
| if (this.tagName === "INPUT" && this.type === "text") | |
| this.value = oldText; | |
| else | |
| this.textContent = oldText; | |
| cleanUpAfterEditing.call(this); | |
| cancelledCallback(this, context); | |
| } | |
| function editingCommitted() | |
| { | |
| cleanUpAfterEditing.call(this); | |
| committedCallback(this, getContent(this), oldText, context, moveDirection); | |
| } | |
| function defaultFinishHandler(event) | |
| { | |
| var isMetaOrCtrl = WebInspector.isMac() ? | |
| event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey : | |
| event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey; | |
| if (isEnterKey(event) && (event.isMetaOrCtrlForTest || !config.multiline || isMetaOrCtrl)) | |
| return "commit"; | |
| else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B") | |
| return "cancel"; | |
| else if (event.keyIdentifier === "U+0009") | |
| return "move-" + (event.shiftKey ? "backward" : "forward"); | |
| } | |
| function handleEditingResult(result, event) | |
| { | |
| if (result === "commit") { | |
| editingCommitted.call(element); | |
| event.consume(true); | |
| } else if (result === "cancel") { | |
| editingCancelled.call(element); | |
| event.consume(true); | |
| } else if (result && result.startsWith("move-")) { | |
| moveDirection = result.substring(5); | |
| if (event.keyIdentifier !== "U+0009") | |
| blurEventListener(); | |
| } | |
| } | |
| function pasteEventListener(event) | |
| { | |
| var result = pasteCallback(event); | |
| handleEditingResult(result, event); | |
| } | |
| function keyDownEventListener(event) | |
| { | |
| var handler = config.customFinishHandler || defaultFinishHandler; | |
| var result = handler(event); | |
| handleEditingResult(result, event); | |
| } | |
| element.addEventListener("blur", blurEventListener, false); | |
| element.addEventListener("keydown", keyDownEventListener, true); | |
| if (pasteCallback) | |
| element.addEventListener("paste", pasteEventListener, true); | |
| WebInspector.setCurrentFocusElement(element); | |
| return { | |
| cancel: editingCancelled.bind(element), | |
| commit: editingCommitted.bind(element) | |
| }; | |
| } | |
| Number.secondsToString = function(seconds, higherResolution) | |
| { | |
| if (seconds === 0) | |
| return "0"; | |
| var ms = seconds * 1000; | |
| if (higherResolution && ms < 1000) | |
| return WebInspector.UIString("%.3fms", ms); | |
| else if (ms < 1000) | |
| return WebInspector.UIString("%.0fms", ms); | |
| if (seconds < 60) | |
| return WebInspector.UIString("%.2fs", seconds); | |
| var minutes = seconds / 60; | |
| if (minutes < 60) | |
| return WebInspector.UIString("%.1fmin", minutes); | |
| var hours = minutes / 60; | |
| if (hours < 24) | |
| return WebInspector.UIString("%.1fhrs", hours); | |
| var days = hours / 24; | |
| return WebInspector.UIString("%.1f days", days); | |
| } | |
| Number.bytesToString = function(bytes, higherResolution) | |
| { | |
| if (typeof higherResolution === "undefined") | |
| higherResolution = true; | |
| if (bytes < 1024) | |
| return WebInspector.UIString("%.0fB", bytes); | |
| var kilobytes = bytes / 1024; | |
| if (higherResolution && kilobytes < 1024) | |
| return WebInspector.UIString("%.2fKB", kilobytes); | |
| else if (kilobytes < 1024) | |
| return WebInspector.UIString("%.0fKB", kilobytes); | |
| var megabytes = kilobytes / 1024; | |
| if (higherResolution) | |
| return WebInspector.UIString("%.2fMB", megabytes); | |
| else | |
| return WebInspector.UIString("%.0fMB", megabytes); | |
| } | |
| Number.withThousandsSeparator = function(num) | |
| { | |
| var str = num + ""; | |
| var re = /(\d+)(\d{3})/; | |
| while (str.match(re)) | |
| str = str.replace(re, "$1\u2009$2"); | |
| return str; | |
| } | |
| WebInspector.useLowerCaseMenuTitles = function() | |
| { | |
| return WebInspector.platform() === "windows" && Preferences.useLowerCaseMenuTitlesOnWindows; | |
| } | |
| WebInspector.formatLocalized = function(format, substitutions, formatters, initialValue, append) | |
| { | |
| return String.format(WebInspector.UIString(format), substitutions, formatters, initialValue, append); | |
| } | |
| WebInspector.openLinkExternallyLabel = function() | |
| { | |
| return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in new tab" : "Open Link in New Tab"); | |
| } | |
| WebInspector.copyLinkAddressLabel = function() | |
| { | |
| return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy link address" : "Copy Link Address"); | |
| } | |
| WebInspector.platform = function() | |
| { | |
| if (!WebInspector._platform) | |
| WebInspector._platform = InspectorFrontendHost.platform(); | |
| return WebInspector._platform; | |
| } | |
| WebInspector.isMac = function() | |
| { | |
| if (typeof WebInspector._isMac === "undefined") | |
| WebInspector._isMac = WebInspector.platform() === "mac"; | |
| return WebInspector._isMac; | |
| } | |
| WebInspector.isWin = function() | |
| { | |
| if (typeof WebInspector._isWin === "undefined") | |
| WebInspector._isWin = WebInspector.platform() === "windows"; | |
| return WebInspector._isWin; | |
| } | |
| WebInspector.PlatformFlavor = { | |
| WindowsVista: "windows-vista", | |
| MacTiger: "mac-tiger", | |
| MacLeopard: "mac-leopard", | |
| MacSnowLeopard: "mac-snowleopard" | |
| } | |
| WebInspector.platformFlavor = function() | |
| { | |
| function detectFlavor() | |
| { | |
| const userAgent = navigator.userAgent; | |
| if (WebInspector.platform() === "windows") { | |
| var match = userAgent.match(/Windows NT (\d+)\.(?:\d+)/); | |
| if (match && match[1] >= 6) | |
| return WebInspector.PlatformFlavor.WindowsVista; | |
| return null; | |
| } else if (WebInspector.platform() === "mac") { | |
| var match = userAgent.match(/Mac OS X\s*(?:(\d+)_(\d+))?/); | |
| if (!match || match[1] != 10) | |
| return WebInspector.PlatformFlavor.MacSnowLeopard; | |
| switch (Number(match[2])) { | |
| case 4: | |
| return WebInspector.PlatformFlavor.MacTiger; | |
| case 5: | |
| return WebInspector.PlatformFlavor.MacLeopard; | |
| case 6: | |
| default: | |
| return WebInspector.PlatformFlavor.MacSnowLeopard; | |
| } | |
| } | |
| } | |
| if (!WebInspector._platformFlavor) | |
| WebInspector._platformFlavor = detectFlavor(); | |
| return WebInspector._platformFlavor; | |
| } | |
| WebInspector.port = function() | |
| { | |
| if (!WebInspector._port) | |
| WebInspector._port = InspectorFrontendHost.port(); | |
| return WebInspector._port; | |
| } | |
| WebInspector.installPortStyles = function() | |
| { | |
| var platform = WebInspector.platform(); | |
| document.body.addStyleClass("platform-" + platform); | |
| var flavor = WebInspector.platformFlavor(); | |
| if (flavor) | |
| document.body.addStyleClass("platform-" + flavor); | |
| var port = WebInspector.port(); | |
| document.body.addStyleClass("port-" + port); | |
| } | |
| WebInspector._windowFocused = function(event) | |
| { | |
| if (event.target.document.nodeType === Node.DOCUMENT_NODE) | |
| document.body.removeStyleClass("inactive"); | |
| } | |
| WebInspector._windowBlurred = function(event) | |
| { | |
| if (event.target.document.nodeType === Node.DOCUMENT_NODE) | |
| document.body.addStyleClass("inactive"); | |
| } | |
| WebInspector.previousFocusElement = function() | |
| { | |
| return WebInspector._previousFocusElement; | |
| } | |
| WebInspector.currentFocusElement = function() | |
| { | |
| return WebInspector._currentFocusElement; | |
| } | |
| WebInspector._focusChanged = function(event) | |
| { | |
| WebInspector.setCurrentFocusElement(event.target); | |
| } | |
| WebInspector._textInputTypes = ["text", "search", "tel", "url", "email", "password"].keySet(); | |
| WebInspector._isTextEditingElement = function(element) | |
| { | |
| if (element instanceof HTMLInputElement) | |
| return element.type in WebInspector._textInputTypes; | |
| if (element instanceof HTMLTextAreaElement) | |
| return true; | |
| return false; | |
| } | |
| WebInspector.setCurrentFocusElement = function(x) | |
| { | |
| if (WebInspector._currentFocusElement !== x) | |
| WebInspector._previousFocusElement = WebInspector._currentFocusElement; | |
| WebInspector._currentFocusElement = x; | |
| if (WebInspector._currentFocusElement) { | |
| WebInspector._currentFocusElement.focus(); | |
| var selection = window.getSelection(); | |
| if (!WebInspector._isTextEditingElement(WebInspector._currentFocusElement) && selection.isCollapsed && !WebInspector._currentFocusElement.isInsertionCaretInside()) { | |
| var selectionRange = WebInspector._currentFocusElement.ownerDocument.createRange(); | |
| selectionRange.setStart(WebInspector._currentFocusElement, 0); | |
| selectionRange.setEnd(WebInspector._currentFocusElement, 0); | |
| selection.removeAllRanges(); | |
| selection.addRange(selectionRange); | |
| } | |
| } else if (WebInspector._previousFocusElement) | |
| WebInspector._previousFocusElement.blur(); | |
| } | |
| WebInspector.restoreFocusFromElement = function(element) | |
| { | |
| if (element && element.isSelfOrAncestor(WebInspector.currentFocusElement())) | |
| WebInspector.setCurrentFocusElement(WebInspector.previousFocusElement()); | |
| } | |
| WebInspector.setToolbarColors = function(backgroundColor, color) | |
| { | |
| if (!WebInspector._themeStyleElement) { | |
| WebInspector._themeStyleElement = document.createElement("style"); | |
| document.head.appendChild(WebInspector._themeStyleElement); | |
| } | |
| WebInspector._themeStyleElement.textContent = | |
| "#toolbar {\ | |
| background-image: none !important;\ | |
| background-color: " + backgroundColor + " !important;\ | |
| }\ | |
| \ | |
| .toolbar-label {\ | |
| color: " + color + " !important;\ | |
| text-shadow: none;\ | |
| }"; | |
| } | |
| WebInspector.resetToolbarColors = function() | |
| { | |
| if (WebInspector._themeStyleElement) | |
| WebInspector._themeStyleElement.textContent = ""; | |
| } | |
| WebInspector.highlightSearchResult = function(element, offset, length, domChanges) | |
| { | |
| var result = WebInspector.highlightSearchResults(element, [{offset: offset, length: length }], domChanges); | |
| return result.length ? result[0] : null; | |
| } | |
| WebInspector.highlightSearchResults = function(element, resultRanges, changes) | |
| { | |
| return WebInspector.highlightRangesWithStyleClass(element, resultRanges, "webkit-search-result", changes); | |
| } | |
| WebInspector.highlightRangesWithStyleClass = function(element, resultRanges, styleClass, changes) | |
| { | |
| changes = changes || []; | |
| var highlightNodes = []; | |
| var lineText = element.textContent; | |
| var ownerDocument = element.ownerDocument; | |
| var textNodeSnapshot = ownerDocument.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); | |
| var snapshotLength = textNodeSnapshot.snapshotLength; | |
| if (snapshotLength === 0) | |
| return highlightNodes; | |
| var nodeRanges = []; | |
| var rangeEndOffset = 0; | |
| for (var i = 0; i < snapshotLength; ++i) { | |
| var range = {}; | |
| range.offset = rangeEndOffset; | |
| range.length = textNodeSnapshot.snapshotItem(i).textContent.length; | |
| rangeEndOffset = range.offset + range.length; | |
| nodeRanges.push(range); | |
| } | |
| var startIndex = 0; | |
| for (var i = 0; i < resultRanges.length; ++i) { | |
| var startOffset = resultRanges[i].offset; | |
| var endOffset = startOffset + resultRanges[i].length; | |
| while (startIndex < snapshotLength && nodeRanges[startIndex].offset + nodeRanges[startIndex].length <= startOffset) | |
| startIndex++; | |
| var endIndex = startIndex; | |
| while (endIndex < snapshotLength && nodeRanges[endIndex].offset + nodeRanges[endIndex].length < endOffset) | |
| endIndex++; | |
| if (endIndex === snapshotLength) | |
| break; | |
| var highlightNode = ownerDocument.createElement("span"); | |
| highlightNode.className = styleClass; | |
| highlightNode.textContent = lineText.substring(startOffset, endOffset); | |
| var lastTextNode = textNodeSnapshot.snapshotItem(endIndex); | |
| var lastText = lastTextNode.textContent; | |
| lastTextNode.textContent = lastText.substring(endOffset - nodeRanges[endIndex].offset); | |
| changes.push({ node: lastTextNode, type: "changed", oldText: lastText, newText: lastTextNode.textContent }); | |
| if (startIndex === endIndex) { | |
| lastTextNode.parentElement.insertBefore(highlightNode, lastTextNode); | |
| changes.push({ node: highlightNode, type: "added", nextSibling: lastTextNode, parent: lastTextNode.parentElement }); | |
| highlightNodes.push(highlightNode); | |
| var prefixNode = ownerDocument.createTextNode(lastText.substring(0, startOffset - nodeRanges[startIndex].offset)); | |
| lastTextNode.parentElement.insertBefore(prefixNode, highlightNode); | |
| changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: lastTextNode.parentElement }); | |
| } else { | |
| var firstTextNode = textNodeSnapshot.snapshotItem(startIndex); | |
| var firstText = firstTextNode.textContent; | |
| var anchorElement = firstTextNode.nextSibling; | |
| firstTextNode.parentElement.insertBefore(highlightNode, anchorElement); | |
| changes.push({ node: highlightNode, type: "added", nextSibling: anchorElement, parent: firstTextNode.parentElement }); | |
| highlightNodes.push(highlightNode); | |
| firstTextNode.textContent = firstText.substring(0, startOffset - nodeRanges[startIndex].offset); | |
| changes.push({ node: firstTextNode, type: "changed", oldText: firstText, newText: firstTextNode.textContent }); | |
| for (var j = startIndex + 1; j < endIndex; j++) { | |
| var textNode = textNodeSnapshot.snapshotItem(j); | |
| var text = textNode.textContent; | |
| textNode.textContent = ""; | |
| changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent }); | |
| } | |
| } | |
| startIndex = endIndex; | |
| nodeRanges[startIndex].offset = endOffset; | |
| nodeRanges[startIndex].length = lastTextNode.textContent.length; | |
| } | |
| return highlightNodes; | |
| } | |
| WebInspector.applyDomChanges = function(domChanges) | |
| { | |
| for (var i = 0, size = domChanges.length; i < size; ++i) { | |
| var entry = domChanges[i]; | |
| switch (entry.type) { | |
| case "added": | |
| entry.parent.insertBefore(entry.node, entry.nextSibling); | |
| break; | |
| case "changed": | |
| entry.node.textContent = entry.newText; | |
| break; | |
| } | |
| } | |
| } | |
| WebInspector.revertDomChanges = function(domChanges) | |
| { | |
| for (var i = domChanges.length - 1; i >= 0; --i) { | |
| var entry = domChanges[i]; | |
| switch (entry.type) { | |
| case "added": | |
| if (entry.node.parentElement) | |
| entry.node.parentElement.removeChild(entry.node); | |
| break; | |
| case "changed": | |
| entry.node.textContent = entry.oldText; | |
| break; | |
| } | |
| } | |
| } | |
| WebInspector._coalescingLevel = 0; | |
| WebInspector.startBatchUpdate = function() | |
| { | |
| if (!WebInspector._coalescingLevel) | |
| WebInspector._postUpdateHandlers = new Map(); | |
| WebInspector._coalescingLevel++; | |
| } | |
| WebInspector.endBatchUpdate = function() | |
| { | |
| if (--WebInspector._coalescingLevel) | |
| return; | |
| var handlers = WebInspector._postUpdateHandlers; | |
| delete WebInspector._postUpdateHandlers; | |
| var keys = handlers.keys(); | |
| for (var i = 0; i < keys.length; ++i) { | |
| var object = keys[i]; | |
| var methods = handlers.get(object).keys(); | |
| for (var j = 0; j < methods.length; ++j) | |
| methods[j].call(object); | |
| } | |
| } | |
| WebInspector.invokeOnceAfterBatchUpdate = function(object, method) | |
| { | |
| if (!WebInspector._coalescingLevel) { | |
| method.call(object); | |
| return; | |
| } | |
| var methods = WebInspector._postUpdateHandlers.get(object); | |
| if (!methods) { | |
| methods = new Map(); | |
| WebInspector._postUpdateHandlers.put(object, methods); | |
| } | |
| methods.put(method); | |
| } | |
| ;(function() { | |
| function windowLoaded() | |
| { | |
| window.addEventListener("focus", WebInspector._windowFocused, false); | |
| window.addEventListener("blur", WebInspector._windowBlurred, false); | |
| document.addEventListener("focus", WebInspector._focusChanged.bind(this), true); | |
| window.removeEventListener("DOMContentLoaded", windowLoaded, false); | |
| } | |
| window.addEventListener("DOMContentLoaded", windowLoaded, false); | |
| })(); | |
| function InspectorBackendClass() | |
| { | |
| this._lastCallbackId = 1; | |
| this._pendingResponsesCount = 0; | |
| this._callbacks = {}; | |
| this._domainDispatchers = {}; | |
| this._eventArgs = {}; | |
| this._replyArgs = {}; | |
| this.dumpInspectorTimeStats = false; | |
| this.dumpInspectorProtocolMessages = false; | |
| this._initialized = false; | |
| } | |
| InspectorBackendClass.prototype = { | |
| _wrap: function(callback, method) | |
| { | |
| var callbackId = this._lastCallbackId++; | |
| if (!callback) | |
| callback = function() {}; | |
| this._callbacks[callbackId] = callback; | |
| callback.methodName = method; | |
| if (this.dumpInspectorTimeStats) | |
| callback.sendRequestTime = Date.now(); | |
| return callbackId; | |
| }, | |
| registerCommand: function(method, signature, replyArgs) | |
| { | |
| var domainAndMethod = method.split("."); | |
| var agentName = domainAndMethod[0] + "Agent"; | |
| if (!window[agentName]) | |
| window[agentName] = {}; | |
| window[agentName][domainAndMethod[1]] = this._sendMessageToBackend.bind(this, method, signature); | |
| window[agentName][domainAndMethod[1]]["invoke"] = this._invoke.bind(this, method, signature); | |
| this._replyArgs[method] = replyArgs; | |
| this._initialized = true; | |
| }, | |
| registerEvent: function(eventName, params) | |
| { | |
| this._eventArgs[eventName] = params; | |
| this._initialized = true; | |
| }, | |
| _invoke: function(method, signature, args, callback) | |
| { | |
| this._wrapCallbackAndSendMessageObject(method, args, callback); | |
| }, | |
| _sendMessageToBackend: function(method, signature, vararg) | |
| { | |
| var args = Array.prototype.slice.call(arguments, 2); | |
| var callback = (args.length && typeof args[args.length - 1] === "function") ? args.pop() : null; | |
| var params = {}; | |
| var hasParams = false; | |
| for (var i = 0; i < signature.length; ++i) { | |
| var param = signature[i]; | |
| var paramName = param["name"]; | |
| var typeName = param["type"]; | |
| var optionalFlag = param["optional"]; | |
| if (!args.length && !optionalFlag) { | |
| console.error("Protocol Error: Invalid number of arguments for method '" + method + "' call. It must have the following arguments '" + JSON.stringify(signature) + "'."); | |
| return; | |
| } | |
| var value = args.shift(); | |
| if (optionalFlag && typeof value === "undefined") { | |
| continue; | |
| } | |
| if (typeof value !== typeName) { | |
| console.error("Protocol Error: Invalid type of argument '" + paramName + "' for method '" + method + "' call. It must be '" + typeName + "' but it is '" + typeof value + "'."); | |
| return; | |
| } | |
| params[paramName] = value; | |
| hasParams = true; | |
| } | |
| if (args.length === 1 && !callback) { | |
| if (typeof args[0] !== "undefined") { | |
| console.error("Protocol Error: Optional callback argument for method '" + method + "' call must be a function but its type is '" + typeof args[0] + "'."); | |
| return; | |
| } | |
| } | |
| this._wrapCallbackAndSendMessageObject(method, hasParams ? params : null, callback); | |
| }, | |
| _wrapCallbackAndSendMessageObject: function(method, params, callback) | |
| { | |
| var messageObject = {}; | |
| messageObject.method = method; | |
| if (params) | |
| messageObject.params = params; | |
| messageObject.id = this._wrap(callback, method); | |
| if (this.dumpInspectorProtocolMessages) | |
| console.log("frontend: " + JSON.stringify(messageObject)); | |
| ++this._pendingResponsesCount; | |
| this.sendMessageObjectToBackend(messageObject); | |
| }, | |
| sendMessageObjectToBackend: function(messageObject) | |
| { | |
| var message = JSON.stringify(messageObject); | |
| InspectorFrontendHost.sendMessageToBackend(message); | |
| }, | |
| registerDomainDispatcher: function(domain, dispatcher) | |
| { | |
| this._domainDispatchers[domain] = dispatcher; | |
| }, | |
| dispatch: function(message) | |
| { | |
| if (this.dumpInspectorProtocolMessages) | |
| console.log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message))); | |
| var messageObject = (typeof message === "string") ? JSON.parse(message) : message; | |
| if ("id" in messageObject) { | |
| if (messageObject.error) { | |
| if (messageObject.error.code !== -32000) | |
| this.reportProtocolError(messageObject); | |
| } | |
| var callback = this._callbacks[messageObject.id]; | |
| if (callback) { | |
| var argumentsArray = []; | |
| if (messageObject.result) { | |
| var paramNames = this._replyArgs[callback.methodName]; | |
| if (paramNames) { | |
| for (var i = 0; i < paramNames.length; ++i) | |
| argumentsArray.push(messageObject.result[paramNames[i]]); | |
| } | |
| } | |
| var processingStartTime; | |
| if (this.dumpInspectorTimeStats && callback.methodName) | |
| processingStartTime = Date.now(); | |
| argumentsArray.unshift(messageObject.error ? messageObject.error.message : null); | |
| callback.apply(null, argumentsArray); | |
| --this._pendingResponsesCount; | |
| delete this._callbacks[messageObject.id]; | |
| if (this.dumpInspectorTimeStats && callback.methodName) | |
| console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime)); | |
| } | |
| if (this._scripts && !this._pendingResponsesCount) | |
| this.runAfterPendingDispatches(); | |
| return; | |
| } else { | |
| var method = messageObject.method.split("."); | |
| var domainName = method[0]; | |
| var functionName = method[1]; | |
| if (!(domainName in this._domainDispatchers)) { | |
| console.error("Protocol Error: the message is for non-existing domain '" + domainName + "'"); | |
| return; | |
| } | |
| var dispatcher = this._domainDispatchers[domainName]; | |
| if (!(functionName in dispatcher)) { | |
| console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.method + "'"); | |
| return; | |
| } | |
| if (!this._eventArgs[messageObject.method]) { | |
| console.error("Protocol Error: Attempted to dispatch an unspecified method '" + messageObject.method + "'"); | |
| return; | |
| } | |
| var params = []; | |
| if (messageObject.params) { | |
| var paramNames = this._eventArgs[messageObject.method]; | |
| for (var i = 0; i < paramNames.length; ++i) | |
| params.push(messageObject.params[paramNames[i]]); | |
| } | |
| var processingStartTime; | |
| if (this.dumpInspectorTimeStats) | |
| processingStartTime = Date.now(); | |
| dispatcher[functionName].apply(dispatcher, params); | |
| if (this.dumpInspectorTimeStats) | |
| console.log("time-stats: " + messageObject.method + " = " + (Date.now() - processingStartTime)); | |
| } | |
| }, | |
| reportProtocolError: function(messageObject) | |
| { | |
| console.error("Request with id = " + messageObject.id + " failed. " + messageObject.error); | |
| }, | |
| runAfterPendingDispatches: function(script) | |
| { | |
| if (!this._scripts) | |
| this._scripts = []; | |
| if (script) | |
| this._scripts.push(script); | |
| if (!this._pendingResponsesCount) { | |
| var scripts = this._scripts; | |
| this._scripts = [] | |
| for (var id = 0; id < scripts.length; ++id) | |
| scripts[id].call(this); | |
| } | |
| }, | |
| loadFromJSONIfNeeded: function(jsonUrl) | |
| { | |
| if (this._initialized) | |
| return; | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("GET", jsonUrl, false); | |
| xhr.send(null); | |
| var schema = JSON.parse(xhr.responseText); | |
| var jsTypes = { integer: "number", array: "object" }; | |
| var rawTypes = {}; | |
| var domains = schema["domains"]; | |
| for (var i = 0; i < domains.length; ++i) { | |
| var domain = domains[i]; | |
| for (var j = 0; domain.types && j < domain.types.length; ++j) { | |
| var type = domain.types[j]; | |
| rawTypes[domain.domain + "." + type.id] = jsTypes[type.type] || type.type; | |
| } | |
| } | |
| var result = []; | |
| for (var i = 0; i < domains.length; ++i) { | |
| var domain = domains[i]; | |
| var commands = domain["commands"] || []; | |
| for (var j = 0; j < commands.length; ++j) { | |
| var command = commands[j]; | |
| var parameters = command["parameters"]; | |
| var paramsText = []; | |
| for (var k = 0; parameters && k < parameters.length; ++k) { | |
| var parameter = parameters[k]; | |
| var type; | |
| if (parameter.type) | |
| type = jsTypes[parameter.type] || parameter.type; | |
| else { | |
| var ref = parameter["$ref"]; | |
| if (ref.indexOf(".") !== -1) | |
| type = rawTypes[ref]; | |
| else | |
| type = rawTypes[domain.domain + "." + ref]; | |
| } | |
| var text = "{\"name\": \"" + parameter.name + "\", \"type\": \"" + type + "\", \"optional\": " + (parameter.optional ? "true" : "false") + "}"; | |
| paramsText.push(text); | |
| } | |
| var returnsText = []; | |
| var returns = command["returns"] || []; | |
| for (var k = 0; k < returns.length; ++k) { | |
| var parameter = returns[k]; | |
| returnsText.push("\"" + parameter.name + "\""); | |
| } | |
| result.push("InspectorBackend.registerCommand(\"" + domain.domain + "." + command.name + "\", [" + paramsText.join(", ") + "], [" + returnsText.join(", ") + "]);"); | |
| } | |
| for (var j = 0; domain.events && j < domain.events.length; ++j) { | |
| var event = domain.events[j]; | |
| var paramsText = []; | |
| for (var k = 0; event.parameters && k < event.parameters.length; ++k) { | |
| var parameter = event.parameters[k]; | |
| paramsText.push("\"" + parameter.name + "\""); | |
| } | |
| result.push("InspectorBackend.registerEvent(\"" + domain.domain + "." + event.name + "\", [" + paramsText.join(", ") + "]);"); | |
| } | |
| result.push("InspectorBackend.register" + domain.domain + "Dispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"" + domain.domain + "\");"); | |
| } | |
| eval(result.join("\n")); | |
| } | |
| } | |
| InspectorBackend = new InspectorBackendClass(); | |
| InspectorBackend.registerInspectorDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Inspector"); | |
| InspectorBackend.registerEvent("Inspector.evaluateForTestInFrontend", ["testCallId", "script"]); | |
| InspectorBackend.registerEvent("Inspector.inspect", ["object", "hints"]); | |
| InspectorBackend.registerCommand("Inspector.enable", [], []); | |
| InspectorBackend.registerCommand("Inspector.disable", [], []); | |
| InspectorBackend.registerMemoryDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Memory"); | |
| InspectorBackend.registerCommand("Memory.getDOMNodeCount", [], ["domGroups", "strings"]); | |
| InspectorBackend.registerCommand("Memory.getProcessMemoryDistribution", [], ["distribution"]); | |
| InspectorBackend.registerPageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Page"); | |
| InspectorBackend.registerEvent("Page.domContentEventFired", ["timestamp"]); | |
| InspectorBackend.registerEvent("Page.loadEventFired", ["timestamp"]); | |
| InspectorBackend.registerEvent("Page.frameNavigated", ["frame"]); | |
| InspectorBackend.registerEvent("Page.frameDetached", ["frameId"]); | |
| InspectorBackend.registerCommand("Page.enable", [], []); | |
| InspectorBackend.registerCommand("Page.disable", [], []); | |
| InspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad", [{"name": "scriptSource", "type": "string", "optional": false}], ["identifier"]); | |
| InspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad", [{"name": "identifier", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.reload", [{"name": "ignoreCache", "type": "boolean", "optional": true}, {"name": "scriptToEvaluateOnLoad", "type": "string", "optional": true}], []); | |
| InspectorBackend.registerCommand("Page.navigate", [{"name": "url", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.getCookies", [], ["cookies", "cookiesString"]); | |
| InspectorBackend.registerCommand("Page.deleteCookie", [{"name": "cookieName", "type": "string", "optional": false}, {"name": "domain", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.getResourceTree", [], ["frameTree"]); | |
| InspectorBackend.registerCommand("Page.getResourceContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], ["content", "base64Encoded"]); | |
| InspectorBackend.registerCommand("Page.searchInResource", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); | |
| InspectorBackend.registerCommand("Page.searchInResources", [{"name": "text", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); | |
| InspectorBackend.registerCommand("Page.setDocumentContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "html", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.canOverrideDeviceMetrics", [], ["result"]); | |
| InspectorBackend.registerCommand("Page.setDeviceMetricsOverride", [{"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "fontScaleFactor", "type": "number", "optional": false}, {"name": "fitWindow", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.setShowPaintRects", [{"name": "result", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.getScriptExecutionStatus", [], ["result"]); | |
| InspectorBackend.registerCommand("Page.setScriptExecutionDisabled", [{"name": "value", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.setGeolocationOverride", [{"name": "latitude", "type": "number", "optional": true}, {"name": "longitude", "type": "number", "optional": true}, {"name": "accuracy", "type": "number", "optional": true}], []); | |
| InspectorBackend.registerCommand("Page.clearGeolocationOverride", [], []); | |
| InspectorBackend.registerCommand("Page.canOverrideGeolocation", [], ["result"]); | |
| InspectorBackend.registerCommand("Page.setDeviceOrientationOverride", [{"name": "alpha", "type": "number", "optional": false}, {"name": "beta", "type": "number", "optional": false}, {"name": "gamma", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("Page.clearDeviceOrientationOverride", [], []); | |
| InspectorBackend.registerCommand("Page.canOverrideDeviceOrientation", [], ["result"]); | |
| InspectorBackend.registerCommand("Page.setTouchEmulationEnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerRuntimeDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Runtime"); | |
| InspectorBackend.registerEvent("Runtime.executionContextCreated", ["context"]); | |
| InspectorBackend.registerCommand("Runtime.evaluate", [{"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}, {"name": "contextId", "type": "number", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]); | |
| InspectorBackend.registerCommand("Runtime.callFunctionOn", [{"name": "objectId", "type": "string", "optional": false}, {"name": "functionDeclaration", "type": "string", "optional": false}, {"name": "arguments", "type": "object", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]); | |
| InspectorBackend.registerCommand("Runtime.getProperties", [{"name": "objectId", "type": "string", "optional": false}, {"name": "ownProperties", "type": "boolean", "optional": true}], ["result"]); | |
| InspectorBackend.registerCommand("Runtime.releaseObject", [{"name": "objectId", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Runtime.releaseObjectGroup", [{"name": "objectGroup", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Runtime.run", [], []); | |
| InspectorBackend.registerCommand("Runtime.setReportExecutionContextCreation", [{"name": "enabled", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerConsoleDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Console"); | |
| InspectorBackend.registerEvent("Console.messageAdded", ["message"]); | |
| InspectorBackend.registerEvent("Console.messageRepeatCountUpdated", ["count"]); | |
| InspectorBackend.registerEvent("Console.messagesCleared", []); | |
| InspectorBackend.registerCommand("Console.enable", [], []); | |
| InspectorBackend.registerCommand("Console.disable", [], []); | |
| InspectorBackend.registerCommand("Console.clearMessages", [], []); | |
| InspectorBackend.registerCommand("Console.setMonitoringXHREnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerCommand("Console.addInspectedNode", [{"name": "nodeId", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("Console.addInspectedHeapObject", [{"name": "heapObjectId", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerNetworkDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network"); | |
| InspectorBackend.registerEvent("Network.requestWillBeSent", ["requestId", "frameId", "loaderId", "documentURL", "request", "timestamp", "initiator", "redirectResponse"]); | |
| InspectorBackend.registerEvent("Network.requestServedFromCache", ["requestId"]); | |
| InspectorBackend.registerEvent("Network.responseReceived", ["requestId", "frameId", "loaderId", "timestamp", "type", "response"]); | |
| InspectorBackend.registerEvent("Network.dataReceived", ["requestId", "timestamp", "dataLength", "encodedDataLength"]); | |
| InspectorBackend.registerEvent("Network.loadingFinished", ["requestId", "timestamp"]); | |
| InspectorBackend.registerEvent("Network.loadingFailed", ["requestId", "timestamp", "errorText", "canceled"]); | |
| InspectorBackend.registerEvent("Network.requestServedFromMemoryCache", ["requestId", "frameId", "loaderId", "documentURL", "timestamp", "initiator", "resource"]); | |
| InspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest", ["requestId", "timestamp", "request"]); | |
| InspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived", ["requestId", "timestamp", "response"]); | |
| InspectorBackend.registerEvent("Network.webSocketCreated", ["requestId", "url"]); | |
| InspectorBackend.registerEvent("Network.webSocketClosed", ["requestId", "timestamp"]); | |
| InspectorBackend.registerEvent("Network.webSocketFrameReceived", ["requestId", "timestamp", "response"]); | |
| InspectorBackend.registerEvent("Network.webSocketFrameError", ["requestId", "timestamp", "errorMessage"]); | |
| InspectorBackend.registerEvent("Network.webSocketFrameSent", ["requestId", "timestamp", "response"]); | |
| InspectorBackend.registerCommand("Network.enable", [], []); | |
| InspectorBackend.registerCommand("Network.disable", [], []); | |
| InspectorBackend.registerCommand("Network.setUserAgentOverride", [{"name": "userAgent", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Network.setExtraHTTPHeaders", [{"name": "headers", "type": "object", "optional": false}], []); | |
| InspectorBackend.registerCommand("Network.getResponseBody", [{"name": "requestId", "type": "string", "optional": false}], ["body", "base64Encoded"]); | |
| InspectorBackend.registerCommand("Network.replayXHR", [{"name": "requestId", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Network.canClearBrowserCache", [], ["result"]); | |
| InspectorBackend.registerCommand("Network.clearBrowserCache", [], []); | |
| InspectorBackend.registerCommand("Network.canClearBrowserCookies", [], ["result"]); | |
| InspectorBackend.registerCommand("Network.clearBrowserCookies", [], []); | |
| InspectorBackend.registerCommand("Network.setCacheDisabled", [{"name": "cacheDisabled", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); | |
| InspectorBackend.registerEvent("Database.addDatabase", ["database"]); | |
| InspectorBackend.registerCommand("Database.enable", [], []); | |
| InspectorBackend.registerCommand("Database.disable", [], []); | |
| InspectorBackend.registerCommand("Database.getDatabaseTableNames", [{"name": "databaseId", "type": "string", "optional": false}], ["tableNames"]); | |
| InspectorBackend.registerCommand("Database.executeSQL", [{"name": "databaseId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "values", "sqlError"]); | |
| InspectorBackend.registerIndexedDBDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "IndexedDB"); | |
| InspectorBackend.registerCommand("IndexedDB.enable", [], []); | |
| InspectorBackend.registerCommand("IndexedDB.disable", [], []); | |
| InspectorBackend.registerCommand("IndexedDB.requestDatabaseNamesForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["securityOriginWithDatabaseNames"]); | |
| InspectorBackend.registerCommand("IndexedDB.requestDatabase", [{"name": "frameId", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}], ["databaseWithObjectStores"]); | |
| InspectorBackend.registerCommand("IndexedDB.requestData", [{"name": "frameId", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}, {"name": "indexName", "type": "string", "optional": false}, {"name": "skipCount", "type": "number", "optional": false}, {"name": "pageSize", "type": "number", "optional": false}, {"name": "keyRange", "type": "object", "optional": true}], ["objectStoreDataEntries", "hasMore"]); | |
| InspectorBackend.registerDOMStorageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOMStorage"); | |
| InspectorBackend.registerEvent("DOMStorage.addDOMStorage", ["storage"]); | |
| InspectorBackend.registerEvent("DOMStorage.domStorageUpdated", ["storageId"]); | |
| InspectorBackend.registerCommand("DOMStorage.enable", [], []); | |
| InspectorBackend.registerCommand("DOMStorage.disable", [], []); | |
| InspectorBackend.registerCommand("DOMStorage.getDOMStorageEntries", [{"name": "storageId", "type": "string", "optional": false}], ["entries"]); | |
| InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem", [{"name": "storageId", "type": "string", "optional": false}, {"name": "key", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], ["success"]); | |
| InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem", [{"name": "storageId", "type": "string", "optional": false}, {"name": "key", "type": "string", "optional": false}], ["success"]); | |
| InspectorBackend.registerApplicationCacheDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "ApplicationCache"); | |
| InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated", ["frameId", "manifestURL", "status"]); | |
| InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated", ["isNowOnline"]); | |
| InspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests", [], ["frameIds"]); | |
| InspectorBackend.registerCommand("ApplicationCache.enable", [], []); | |
| InspectorBackend.registerCommand("ApplicationCache.getManifestForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["manifestURL"]); | |
| InspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["applicationCache"]); | |
| InspectorBackend.registerFileSystemDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "FileSystem"); | |
| InspectorBackend.registerCommand("FileSystem.enable", [], []); | |
| InspectorBackend.registerCommand("FileSystem.disable", [], []); | |
| InspectorBackend.registerCommand("FileSystem.requestFileSystemRoot", [{"name": "origin", "type": "string", "optional": false}, {"name": "type", "type": "string", "optional": false}], ["errorCode", "root"]); | |
| InspectorBackend.registerCommand("FileSystem.requestDirectoryContent", [{"name": "url", "type": "string", "optional": false}], ["errorCode", "entries"]); | |
| InspectorBackend.registerCommand("FileSystem.requestMetadata", [{"name": "url", "type": "string", "optional": false}], ["errorCode", "metadata"]); | |
| InspectorBackend.registerCommand("FileSystem.requestFileContent", [{"name": "url", "type": "string", "optional": false}, {"name": "readAsText", "type": "boolean", "optional": false}, {"name": "start", "type": "number", "optional": true}, {"name": "end", "type": "number", "optional": true}, {"name": "charset", "type": "string", "optional": true}], ["errorCode", "content", "charset"]); | |
| InspectorBackend.registerCommand("FileSystem.deleteEntry", [{"name": "url", "type": "string", "optional": false}], ["errorCode"]); | |
| InspectorBackend.registerDOMDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOM"); | |
| InspectorBackend.registerEvent("DOM.documentUpdated", []); | |
| InspectorBackend.registerEvent("DOM.setChildNodes", ["parentId", "nodes"]); | |
| InspectorBackend.registerEvent("DOM.attributeModified", ["nodeId", "name", "value"]); | |
| InspectorBackend.registerEvent("DOM.attributeRemoved", ["nodeId", "name"]); | |
| InspectorBackend.registerEvent("DOM.inlineStyleInvalidated", ["nodeIds"]); | |
| InspectorBackend.registerEvent("DOM.characterDataModified", ["nodeId", "characterData"]); | |
| InspectorBackend.registerEvent("DOM.childNodeCountUpdated", ["nodeId", "childNodeCount"]); | |
| InspectorBackend.registerEvent("DOM.childNodeInserted", ["parentNodeId", "previousNodeId", "node"]); | |
| InspectorBackend.registerEvent("DOM.childNodeRemoved", ["parentNodeId", "nodeId"]); | |
| InspectorBackend.registerEvent("DOM.shadowRootPushed", ["hostId", "root"]); | |
| InspectorBackend.registerEvent("DOM.shadowRootPopped", ["hostId", "rootId"]); | |
| InspectorBackend.registerCommand("DOM.getDocument", [], ["root"]); | |
| InspectorBackend.registerCommand("DOM.requestChildNodes", [{"name": "nodeId", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.querySelector", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeId"]); | |
| InspectorBackend.registerCommand("DOM.querySelectorAll", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeIds"]); | |
| InspectorBackend.registerCommand("DOM.setNodeName", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], ["nodeId"]); | |
| InspectorBackend.registerCommand("DOM.setNodeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.removeNode", [{"name": "nodeId", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.setAttributeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.setAttributesAsText", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "name", "type": "string", "optional": true}], []); | |
| InspectorBackend.registerCommand("DOM.removeAttribute", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.getEventListenersForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["listeners"]); | |
| InspectorBackend.registerCommand("DOM.getOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}], ["outerHTML"]); | |
| InspectorBackend.registerCommand("DOM.setOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "outerHTML", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.performSearch", [{"name": "query", "type": "string", "optional": false}], ["searchId", "resultCount"]); | |
| InspectorBackend.registerCommand("DOM.getSearchResults", [{"name": "searchId", "type": "string", "optional": false}, {"name": "fromIndex", "type": "number", "optional": false}, {"name": "toIndex", "type": "number", "optional": false}], ["nodeIds"]); | |
| InspectorBackend.registerCommand("DOM.discardSearchResults", [{"name": "searchId", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.requestNode", [{"name": "objectId", "type": "string", "optional": false}], ["nodeId"]); | |
| InspectorBackend.registerCommand("DOM.setInspectModeEnabled", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": true}], []); | |
| InspectorBackend.registerCommand("DOM.highlightRect", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}], []); | |
| InspectorBackend.registerCommand("DOM.highlightNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOM.hideHighlight", [], []); | |
| InspectorBackend.registerCommand("DOM.highlightFrame", [{"name": "frameId", "type": "string", "optional": false}, {"name": "contentColor", "type": "object", "optional": true}, {"name": "contentOutlineColor", "type": "object", "optional": true}], []); | |
| InspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend", [{"name": "path", "type": "string", "optional": false}], ["nodeId"]); | |
| InspectorBackend.registerCommand("DOM.resolveNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["object"]); | |
| InspectorBackend.registerCommand("DOM.getAttributes", [{"name": "nodeId", "type": "number", "optional": false}], ["attributes"]); | |
| InspectorBackend.registerCommand("DOM.moveTo", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "targetNodeId", "type": "number", "optional": false}, {"name": "insertBeforeNodeId", "type": "number", "optional": true}], ["nodeId"]); | |
| InspectorBackend.registerCommand("DOM.undo", [], []); | |
| InspectorBackend.registerCommand("DOM.redo", [], []); | |
| InspectorBackend.registerCommand("DOM.markUndoableState", [], []); | |
| InspectorBackend.registerCSSDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "CSS"); | |
| InspectorBackend.registerEvent("CSS.mediaQueryResultChanged", []); | |
| InspectorBackend.registerEvent("CSS.styleSheetChanged", ["styleSheetId"]); | |
| InspectorBackend.registerEvent("CSS.namedFlowCreated", ["namedFlow"]); | |
| InspectorBackend.registerEvent("CSS.namedFlowRemoved", ["documentNodeId", "flowName"]); | |
| InspectorBackend.registerEvent("CSS.regionLayoutUpdated", ["namedFlow"]); | |
| InspectorBackend.registerCommand("CSS.enable", [], []); | |
| InspectorBackend.registerCommand("CSS.disable", [], []); | |
| InspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "includePseudo", "type": "boolean", "optional": true}, {"name": "includeInherited", "type": "boolean", "optional": true}], ["matchedCSSRules", "pseudoElements", "inherited"]); | |
| InspectorBackend.registerCommand("CSS.getInlineStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["inlineStyle", "attributesStyle"]); | |
| InspectorBackend.registerCommand("CSS.getComputedStyleForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["computedStyle"]); | |
| InspectorBackend.registerCommand("CSS.getAllStyleSheets", [], ["headers"]); | |
| InspectorBackend.registerCommand("CSS.getStyleSheet", [{"name": "styleSheetId", "type": "string", "optional": false}], ["styleSheet"]); | |
| InspectorBackend.registerCommand("CSS.getStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}], ["text"]); | |
| InspectorBackend.registerCommand("CSS.setStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "text", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("CSS.setPropertyText", [{"name": "styleId", "type": "object", "optional": false}, {"name": "propertyIndex", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "overwrite", "type": "boolean", "optional": false}], ["style"]); | |
| InspectorBackend.registerCommand("CSS.toggleProperty", [{"name": "styleId", "type": "object", "optional": false}, {"name": "propertyIndex", "type": "number", "optional": false}, {"name": "disable", "type": "boolean", "optional": false}], ["style"]); | |
| InspectorBackend.registerCommand("CSS.setRuleSelector", [{"name": "ruleId", "type": "object", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]); | |
| InspectorBackend.registerCommand("CSS.addRule", [{"name": "contextNodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]); | |
| InspectorBackend.registerCommand("CSS.getSupportedCSSProperties", [], ["cssProperties"]); | |
| InspectorBackend.registerCommand("CSS.forcePseudoState", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": false}], []); | |
| InspectorBackend.registerCommand("CSS.startSelectorProfiler", [], []); | |
| InspectorBackend.registerCommand("CSS.stopSelectorProfiler", [], ["profile"]); | |
| InspectorBackend.registerCommand("CSS.getNamedFlowCollection", [{"name": "documentNodeId", "type": "number", "optional": false}], ["namedFlows"]); | |
| InspectorBackend.registerTimelineDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Timeline"); | |
| InspectorBackend.registerEvent("Timeline.eventRecorded", ["record"]); | |
| InspectorBackend.registerCommand("Timeline.start", [{"name": "maxCallStackDepth", "type": "number", "optional": true}], []); | |
| InspectorBackend.registerCommand("Timeline.stop", [], []); | |
| InspectorBackend.registerCommand("Timeline.setIncludeMemoryDetails", [{"name": "enabled", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerCommand("Timeline.supportsFrameInstrumentation", [], ["result"]); | |
| InspectorBackend.registerDebuggerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Debugger"); | |
| InspectorBackend.registerEvent("Debugger.globalObjectCleared", []); | |
| InspectorBackend.registerEvent("Debugger.scriptParsed", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "isContentScript", "sourceMapURL"]); | |
| InspectorBackend.registerEvent("Debugger.scriptFailedToParse", ["url", "scriptSource", "startLine", "errorLine", "errorMessage"]); | |
| InspectorBackend.registerEvent("Debugger.breakpointResolved", ["breakpointId", "location"]); | |
| InspectorBackend.registerEvent("Debugger.paused", ["callFrames", "reason", "data"]); | |
| InspectorBackend.registerEvent("Debugger.resumed", []); | |
| InspectorBackend.registerCommand("Debugger.causesRecompilation", [], ["result"]); | |
| InspectorBackend.registerCommand("Debugger.supportsSeparateScriptCompilationAndExecution", [], ["result"]); | |
| InspectorBackend.registerCommand("Debugger.enable", [], []); | |
| InspectorBackend.registerCommand("Debugger.disable", [], []); | |
| InspectorBackend.registerCommand("Debugger.setBreakpointsActive", [{"name": "active", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerCommand("Debugger.setBreakpointByUrl", [{"name": "lineNumber", "type": "number", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "urlRegex", "type": "string", "optional": true}, {"name": "columnNumber", "type": "number", "optional": true}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "locations"]); | |
| InspectorBackend.registerCommand("Debugger.setBreakpoint", [{"name": "location", "type": "object", "optional": false}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "actualLocation"]); | |
| InspectorBackend.registerCommand("Debugger.removeBreakpoint", [{"name": "breakpointId", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Debugger.continueToLocation", [{"name": "location", "type": "object", "optional": false}], []); | |
| InspectorBackend.registerCommand("Debugger.stepOver", [], []); | |
| InspectorBackend.registerCommand("Debugger.stepInto", [], []); | |
| InspectorBackend.registerCommand("Debugger.stepOut", [], []); | |
| InspectorBackend.registerCommand("Debugger.pause", [], []); | |
| InspectorBackend.registerCommand("Debugger.resume", [], []); | |
| InspectorBackend.registerCommand("Debugger.searchInContent", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); | |
| InspectorBackend.registerCommand("Debugger.canSetScriptSource", [], ["result"]); | |
| InspectorBackend.registerCommand("Debugger.setScriptSource", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "scriptSource", "type": "string", "optional": false}, {"name": "preview", "type": "boolean", "optional": true}], ["callFrames", "result"]); | |
| InspectorBackend.registerCommand("Debugger.restartFrame", [{"name": "callFrameId", "type": "string", "optional": false}], ["callFrames", "result"]); | |
| InspectorBackend.registerCommand("Debugger.getScriptSource", [{"name": "scriptId", "type": "string", "optional": false}], ["scriptSource"]); | |
| InspectorBackend.registerCommand("Debugger.getFunctionDetails", [{"name": "functionId", "type": "string", "optional": false}], ["details"]); | |
| InspectorBackend.registerCommand("Debugger.setPauseOnExceptions", [{"name": "state", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("Debugger.evaluateOnCallFrame", [{"name": "callFrameId", "type": "string", "optional": false}, {"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]); | |
| InspectorBackend.registerCommand("Debugger.compileScript", [{"name": "expression", "type": "string", "optional": false}, {"name": "sourceURL", "type": "string", "optional": false}], ["scriptId", "syntaxErrorMessage"]); | |
| InspectorBackend.registerCommand("Debugger.runScript", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "contextId", "type": "number", "optional": true}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}], ["result", "wasThrown"]); | |
| InspectorBackend.registerCommand("Debugger.setOverlayMessage", [{"name": "message", "type": "string", "optional": true}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.setInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.removeInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerProfilerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Profiler"); | |
| InspectorBackend.registerEvent("Profiler.addProfileHeader", ["header"]); | |
| InspectorBackend.registerEvent("Profiler.addHeapSnapshotChunk", ["uid", "chunk"]); | |
| InspectorBackend.registerEvent("Profiler.finishHeapSnapshot", ["uid"]); | |
| InspectorBackend.registerEvent("Profiler.setRecordingProfile", ["isProfiling"]); | |
| InspectorBackend.registerEvent("Profiler.resetProfiles", []); | |
| InspectorBackend.registerEvent("Profiler.reportHeapSnapshotProgress", ["done", "total"]); | |
| InspectorBackend.registerCommand("Profiler.causesRecompilation", [], ["result"]); | |
| InspectorBackend.registerCommand("Profiler.isSampling", [], ["result"]); | |
| InspectorBackend.registerCommand("Profiler.hasHeapProfiler", [], ["result"]); | |
| InspectorBackend.registerCommand("Profiler.enable", [], []); | |
| InspectorBackend.registerCommand("Profiler.disable", [], []); | |
| InspectorBackend.registerCommand("Profiler.start", [], []); | |
| InspectorBackend.registerCommand("Profiler.stop", [], []); | |
| InspectorBackend.registerCommand("Profiler.getProfileHeaders", [], ["headers"]); | |
| InspectorBackend.registerCommand("Profiler.getProfile", [{"name": "type", "type": "string", "optional": false}, {"name": "uid", "type": "number", "optional": false}], ["profile"]); | |
| InspectorBackend.registerCommand("Profiler.removeProfile", [{"name": "type", "type": "string", "optional": false}, {"name": "uid", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("Profiler.clearProfiles", [], []); | |
| InspectorBackend.registerCommand("Profiler.takeHeapSnapshot", [], []); | |
| InspectorBackend.registerCommand("Profiler.collectGarbage", [], []); | |
| InspectorBackend.registerCommand("Profiler.getObjectByHeapObjectId", [{"name": "objectId", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["result"]); | |
| InspectorBackend.registerCommand("Profiler.getHeapObjectId", [{"name": "objectId", "type": "string", "optional": false}], ["heapSnapshotObjectId"]); | |
| InspectorBackend.registerWorkerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Worker"); | |
| InspectorBackend.registerEvent("Worker.workerCreated", ["workerId", "url", "inspectorConnected"]); | |
| InspectorBackend.registerEvent("Worker.workerTerminated", ["workerId"]); | |
| InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker", ["workerId", "message"]); | |
| InspectorBackend.registerEvent("Worker.disconnectedFromWorker", []); | |
| InspectorBackend.registerCommand("Worker.enable", [], []); | |
| InspectorBackend.registerCommand("Worker.disable", [], []); | |
| InspectorBackend.registerCommand("Worker.sendMessageToWorker", [{"name": "workerId", "type": "number", "optional": false}, {"name": "message", "type": "object", "optional": false}], []); | |
| InspectorBackend.registerCommand("Worker.connectToWorker", [{"name": "workerId", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("Worker.disconnectFromWorker", [{"name": "workerId", "type": "number", "optional": false}], []); | |
| InspectorBackend.registerCommand("Worker.setAutoconnectToWorkers", [{"name": "value", "type": "boolean", "optional": false}], []); | |
| InspectorBackend.registerWebGLDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "WebGL"); | |
| InspectorBackend.registerCommand("WebGL.enable", [], []); | |
| InspectorBackend.registerCommand("WebGL.disable", [], []); | |
| InspectorBackend.registerCommand("WebGL.dropTraceLog", [{"name": "traceLogId", "type": "string", "optional": false}], []); | |
| InspectorBackend.registerCommand("WebGL.captureFrame", [], ["traceLogId"]); | |
| InspectorBackend.registerCommand("WebGL.getTraceLog", [{"name": "traceLogId", "type": "string", "optional": false}], ["traceLog"]); | |
| InspectorBackend.registerCommand("WebGL.replayTraceLog", [{"name": "traceLogId", "type": "string", "optional": false}, {"name": "stepNo", "type": "number", "optional": false}], ["screenshotDataUrl"]); | |
| if (!window.InspectorExtensionRegistry) { | |
| WebInspector.InspectorExtensionRegistryStub = function() | |
| { | |
| } | |
| WebInspector.InspectorExtensionRegistryStub.prototype = { | |
| getExtensionsAsync: function() | |
| { | |
| } | |
| } | |
| var InspectorExtensionRegistry = new WebInspector.InspectorExtensionRegistryStub(); | |
| } | |
| InspectorFrontendAPI = { | |
| _pendingCommands: [], | |
| isDebuggingEnabled: function() | |
| { | |
| return WebInspector.debuggerModel.debuggerEnabled(); | |
| }, | |
| setDebuggingEnabled: function(enabled) | |
| { | |
| if (enabled) { | |
| WebInspector.debuggerModel.enableDebugger(); | |
| WebInspector.showPanel("scripts"); | |
| } else | |
| WebInspector.debuggerModel.disableDebugger(); | |
| }, | |
| isTimelineProfilingEnabled: function() | |
| { | |
| return WebInspector.panels.timeline && WebInspector.panels.timeline.timelineProfilingEnabled; | |
| }, | |
| setTimelineProfilingEnabled: function(enabled) | |
| { | |
| WebInspector.showPanel("timeline").setTimelineProfilingEnabled(enabled); | |
| }, | |
| isProfilingJavaScript: function() | |
| { | |
| return WebInspector.panels.profiles && WebInspector.CPUProfileType.instance && WebInspector.CPUProfileType.instance.isRecordingProfile(); | |
| }, | |
| startProfilingJavaScript: function() | |
| { | |
| WebInspector.showPanel("profiles").enableProfiler(); | |
| if (WebInspector.CPUProfileType.instance) | |
| WebInspector.CPUProfileType.instance.startRecordingProfile(); | |
| }, | |
| stopProfilingJavaScript: function() | |
| { | |
| WebInspector.showPanel("profiles"); | |
| if (WebInspector.CPUProfileType.instance) | |
| WebInspector.CPUProfileType.instance.stopRecordingProfile(); | |
| }, | |
| setAttachedWindow: function(attached) | |
| { | |
| WebInspector.attached = attached; | |
| }, | |
| showConsole: function() | |
| { | |
| WebInspector.showPanel("console"); | |
| }, | |
| showMainResourceForFrame: function(frameId) | |
| { | |
| }, | |
| showResources: function() | |
| { | |
| WebInspector.showPanel("resources"); | |
| }, | |
| setDockingUnavailable: function(unavailable) | |
| { | |
| WebInspector.setDockingUnavailable(unavailable); | |
| }, | |
| enterInspectElementMode: function() | |
| { | |
| WebInspector.toggleSearchingForNode(); | |
| }, | |
| savedURL: function(url) | |
| { | |
| WebInspector.fileManager.savedURL(url); | |
| }, | |
| appendedToURL: function(url) | |
| { | |
| WebInspector.fileManager.appendedToURL(url); | |
| }, | |
| setToolbarColors: function(backgroundColor, color) | |
| { | |
| WebInspector.setToolbarColors(backgroundColor, color); | |
| }, | |
| evaluateForTest: function(callId, script) | |
| { | |
| WebInspector.evaluateForTestInFrontend(callId, script); | |
| }, | |
| dispatch: function(signature) | |
| { | |
| if (InspectorFrontendAPI._isLoaded) { | |
| var methodName = signature.shift(); | |
| return InspectorFrontendAPI[methodName].apply(InspectorFrontendAPI, signature); | |
| } | |
| InspectorFrontendAPI._pendingCommands.push(signature); | |
| }, | |
| dispatchQueryParameters: function() | |
| { | |
| if ("dispatch" in WebInspector.queryParamsObject) | |
| InspectorFrontendAPI.dispatch(JSON.parse(window.decodeURI(WebInspector.queryParamsObject["dispatch"]))); | |
| }, | |
| loadTimelineFromURL: function(url) | |
| { | |
| WebInspector.showPanel("timeline").loadFromURL(url); | |
| }, | |
| loadCompleted: function() | |
| { | |
| InspectorFrontendAPI._isLoaded = true; | |
| for (var i = 0; i < InspectorFrontendAPI._pendingCommands.length; ++i) | |
| InspectorFrontendAPI.dispatch(InspectorFrontendAPI._pendingCommands[i]); | |
| InspectorFrontendAPI._pendingCommands = []; | |
| if (window.opener) | |
| window.opener.postMessage(["loadCompleted"], "*"); | |
| } | |
| } | |
| if (window.opener) { | |
| function onMessageFromOpener(event) | |
| { | |
| if (event.source === window.opener) | |
| InspectorFrontendAPI.dispatch(event.data); | |
| } | |
| window.addEventListener("message", onMessageFromOpener, true); | |
| } | |
| WebInspector.Object = function() { | |
| } | |
| WebInspector.Object.prototype = { | |
| addEventListener: function(eventType, listener, thisObject) | |
| { | |
| console.assert(listener); | |
| if (!this._listeners) | |
| this._listeners = {}; | |
| if (!this._listeners[eventType]) | |
| this._listeners[eventType] = []; | |
| this._listeners[eventType].push({ thisObject: thisObject, listener: listener }); | |
| }, | |
| removeEventListener: function(eventType, listener, thisObject) | |
| { | |
| console.assert(listener); | |
| if (!this._listeners || !this._listeners[eventType]) | |
| return; | |
| var listeners = this._listeners[eventType]; | |
| for (var i = 0; i < listeners.length; ++i) { | |
| if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject) | |
| listeners.splice(i, 1); | |
| else if (!listener && thisObject && listeners[i].thisObject === thisObject) | |
| listeners.splice(i, 1); | |
| } | |
| if (!listeners.length) | |
| delete this._listeners[eventType]; | |
| }, | |
| removeAllListeners: function() | |
| { | |
| delete this._listeners; | |
| }, | |
| hasEventListeners: function(eventType) | |
| { | |
| if (!this._listeners || !this._listeners[eventType]) | |
| return false; | |
| return true; | |
| }, | |
| dispatchEventToListeners: function(eventType, eventData) | |
| { | |
| if (!this._listeners || !this._listeners[eventType]) | |
| return false; | |
| var event = new WebInspector.Event(this, eventType, eventData); | |
| var listeners = this._listeners[eventType].slice(0); | |
| for (var i = 0; i < listeners.length; ++i) { | |
| listeners[i].listener.call(listeners[i].thisObject, event); | |
| if (event._stoppedPropagation) | |
| break; | |
| } | |
| return event.defaultPrevented; | |
| } | |
| } | |
| WebInspector.Event = function(target, type, data) | |
| { | |
| this.target = target; | |
| this.type = type; | |
| this.data = data; | |
| this.defaultPrevented = false; | |
| this._stoppedPropagation = false; | |
| } | |
| WebInspector.Event.prototype = { | |
| stopPropagation: function() | |
| { | |
| this._stoppedPropagation = true; | |
| }, | |
| preventDefault: function() | |
| { | |
| this.defaultPrevented = true; | |
| }, | |
| consume: function(preventDefault) | |
| { | |
| this.stopPropagation(); | |
| if (preventDefault) | |
| this.preventDefault(); | |
| } | |
| } | |
| WebInspector.notifications = new WebInspector.Object(); | |
| var Preferences = { | |
| maxInlineTextChildLength: 80, | |
| minConsoleHeight: 75, | |
| minSidebarWidth: 100, | |
| minElementsSidebarWidth: 200, | |
| minScriptsSidebarWidth: 200, | |
| styleRulesExpandedState: {}, | |
| showMissingLocalizedStrings: false, | |
| useLowerCaseMenuTitlesOnWindows: false, | |
| sharedWorkersDebugNote: undefined, | |
| localizeUI: true, | |
| exposeDisableCache: false, | |
| applicationTitle: "Web Inspector - %s", | |
| showDockToRight: false, | |
| exposeFileSystemInspection: false | |
| } | |
| var Capabilities = { | |
| samplingCPUProfiler: false, | |
| debuggerCausesRecompilation: true, | |
| separateScriptCompilationAndExecutionEnabled: false, | |
| profilerCausesRecompilation: true, | |
| heapProfilerPresent: false, | |
| canOverrideDeviceMetrics: false, | |
| timelineSupportsFrameInstrumentation: false, | |
| canOverrideGeolocation: false, | |
| canOverrideDeviceOrientation: false, | |
| } | |
| WebInspector.Settings = function() | |
| { | |
| this._eventSupport = new WebInspector.Object(); | |
| this.colorFormat = this.createSetting("colorFormat", "hex"); | |
| this.consoleHistory = this.createSetting("consoleHistory", []); | |
| this.debuggerEnabled = this.createSetting("debuggerEnabled", false); | |
| this.domWordWrap = this.createSetting("domWordWrap", true); | |
| this.profilerEnabled = this.createSetting("profilerEnabled", false); | |
| this.eventListenersFilter = this.createSetting("eventListenersFilter", "all"); | |
| this.lastActivePanel = this.createSetting("lastActivePanel", "elements"); | |
| this.lastViewedScriptFile = this.createSetting("lastViewedScriptFile", "application"); | |
| this.monitoringXHREnabled = this.createSetting("monitoringXHREnabled", false); | |
| this.preserveConsoleLog = this.createSetting("preserveConsoleLog", false); | |
| this.resourcesLargeRows = this.createSetting("resourcesLargeRows", true); | |
| this.resourcesSortOptions = this.createSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"}); | |
| this.resourceViewTab = this.createSetting("resourceViewTab", "preview"); | |
| this.showInheritedComputedStyleProperties = this.createSetting("showInheritedComputedStyleProperties", false); | |
| this.showUserAgentStyles = this.createSetting("showUserAgentStyles", true); | |
| this.watchExpressions = this.createSetting("watchExpressions", []); | |
| this.breakpoints = this.createSetting("breakpoints", []); | |
| this.eventListenerBreakpoints = this.createSetting("eventListenerBreakpoints", []); | |
| this.domBreakpoints = this.createSetting("domBreakpoints", []); | |
| this.xhrBreakpoints = this.createSetting("xhrBreakpoints", []); | |
| this.sourceMapsEnabled = this.createSetting("sourceMapsEnabled", false); | |
| this.cacheDisabled = this.createSetting("cacheDisabled", false); | |
| this.overrideUserAgent = this.createSetting("overrideUserAgent", ""); | |
| this.userAgent = this.createSetting("userAgent", ""); | |
| this.deviceMetrics = this.createSetting("deviceMetrics", ""); | |
| this.deviceFitWindow = this.createSetting("deviceFitWindow", false); | |
| this.showScriptFolders = this.createSetting("showScriptFolders", true); | |
| this.dockToRight = this.createSetting("dockToRight", false); | |
| this.emulateTouchEvents = this.createSetting("emulateTouchEvents", false); | |
| this.showPaintRects = this.createSetting("showPaintRects", false); | |
| this.zoomLevel = this.createSetting("zoomLevel", 0); | |
| this.savedURLs = this.createSetting("savedURLs", {}); | |
| this.javaScriptDisabled = this.createSetting("javaScriptDisabled", false); | |
| this.geolocationOverride = this.createSetting("geolocationOverride", ""); | |
| this.deviceOrientationOverride = this.createSetting("deviceOrientationOverride", ""); | |
| this.showHeapSnapshotObjectsHiddenProperties = this.createSetting("showHeaSnapshotObjectsHiddenProperties", false); | |
| this.searchInContentScripts = this.createSetting("searchInContentScripts", false); | |
| this.textEditorIndent = this.createSetting("textEditorIndent", " "); | |
| if (this.breakpoints.get().length > 500000) | |
| this.breakpoints.set([]); | |
| } | |
| WebInspector.Settings.prototype = { | |
| createSetting: function(key, defaultValue) | |
| { | |
| return new WebInspector.Setting(key, defaultValue, this._eventSupport); | |
| } | |
| } | |
| WebInspector.Setting = function(name, defaultValue, eventSupport) | |
| { | |
| this._name = name; | |
| this._defaultValue = defaultValue; | |
| this._eventSupport = eventSupport; | |
| } | |
| WebInspector.Setting.prototype = { | |
| addChangeListener: function(listener, thisObject) | |
| { | |
| this._eventSupport.addEventListener(this._name, listener, thisObject); | |
| }, | |
| removeChangeListener: function(listener, thisObject) | |
| { | |
| this._eventSupport.removeEventListener(this._name, listener, thisObject); | |
| }, | |
| get name() | |
| { | |
| return this._name; | |
| }, | |
| get: function() | |
| { | |
| if (typeof this._value !== "undefined") | |
| return this._value; | |
| this._value = this._defaultValue; | |
| if (window.localStorage != null && this._name in window.localStorage) { | |
| try { | |
| this._value = JSON.parse(window.localStorage[this._name]); | |
| } catch(e) { | |
| window.localStorage.removeItem(this._name); | |
| } | |
| } | |
| return this._value; | |
| }, | |
| set: function(value) | |
| { | |
| this._value = value; | |
| if (window.localStorage != null) { | |
| try { | |
| window.localStorage[this._name] = JSON.stringify(value); | |
| } catch(e) { | |
| console.error("Error saving setting with name:" + this._name); | |
| } | |
| } | |
| this._eventSupport.dispatchEventToListeners(this._name, value); | |
| } | |
| } | |
| WebInspector.ExperimentsSettings = function() | |
| { | |
| this._setting = WebInspector.settings.createSetting("experiments", {}); | |
| this._experiments = []; | |
| this._enabledForTest = {}; | |
| this.showShadowDOM = this._createExperiment("showShadowDOM", "Show shadow DOM"); | |
| this.snippetsSupport = this._createExperiment("snippetsSupport", "Snippets support"); | |
| this.nativeMemorySnapshots = this._createExperiment("nativeMemorySnapshots", "Native memory profiling"); | |
| this.liveNativeMemoryChart = this._createExperiment("liveNativeMemoryChart", "Live native memory chart"); | |
| this.fileSystemInspection = this._createExperiment("fileSystemInspection", "FileSystem inspection"); | |
| this.webGLInspection = this._createExperiment("webGLInspection ", "WebGL inspection"); | |
| this.mainThreadMonitoring = this._createExperiment("mainThreadMonitoring", "Show CPU activity in Timeline"); | |
| this.geolocationOverride = this._createExperiment("geolocationOverride", "Override Device Geolocation"); | |
| this.deviceOrientationOverride = this._createExperiment("deviceOrientationOverride", "Override Device Orientation"); | |
| this.sass = this._createExperiment("sass", "Support for SASS"); | |
| this.codemirror = this._createExperiment("codemirror", "Use CodeMirror editor"); | |
| this.cssRegions = this._createExperiment("cssRegions", "CSS Regions Support"); | |
| this._cleanUpSetting(); | |
| } | |
| WebInspector.ExperimentsSettings.prototype = { | |
| get experiments() | |
| { | |
| return this._experiments.slice(); | |
| }, | |
| get experimentsEnabled() | |
| { | |
| return "experiments" in WebInspector.queryParamsObject; | |
| }, | |
| _createExperiment: function(experimentName, experimentTitle) | |
| { | |
| var experiment = new WebInspector.Experiment(this, experimentName, experimentTitle); | |
| this._experiments.push(experiment); | |
| return experiment; | |
| }, | |
| isEnabled: function(experimentName) | |
| { | |
| if (this._enabledForTest[experimentName]) | |
| return true; | |
| if (!this.experimentsEnabled) | |
| return false; | |
| var experimentsSetting = this._setting.get(); | |
| return experimentsSetting[experimentName]; | |
| }, | |
| setEnabled: function(experimentName, enabled) | |
| { | |
| var experimentsSetting = this._setting.get(); | |
| experimentsSetting[experimentName] = enabled; | |
| this._setting.set(experimentsSetting); | |
| }, | |
| _enableForTest: function(experimentName) | |
| { | |
| this._enabledForTest[experimentName] = true; | |
| }, | |
| _cleanUpSetting: function() | |
| { | |
| var experimentsSetting = this._setting.get(); | |
| var cleanedUpExperimentSetting = {}; | |
| for (var i = 0; i < this._experiments.length; ++i) { | |
| var experimentName = this._experiments[i].name; | |
| if (experimentsSetting[experimentName]) | |
| cleanedUpExperimentSetting[experimentName] = true; | |
| } | |
| this._setting.set(cleanedUpExperimentSetting); | |
| } | |
| } | |
| WebInspector.Experiment = function(experimentsSettings, name, title) | |
| { | |
| this._name = name; | |
| this._title = title; | |
| this._experimentsSettings = experimentsSettings; | |
| } | |
| WebInspector.Experiment.prototype = { | |
| get name() | |
| { | |
| return this._name; | |
| }, | |
| get title() | |
| { | |
| return this._title; | |
| }, | |
| isEnabled: function() | |
| { | |
| return this._experimentsSettings.isEnabled(this._name); | |
| }, | |
| setEnabled: function(enabled) | |
| { | |
| return this._experimentsSettings.setEnabled(this._name, enabled); | |
| }, | |
| enableForTest: function() | |
| { | |
| this._experimentsSettings._enableForTest(this._name); | |
| } | |
| } | |
| WebInspector.settings = new WebInspector.Settings(); | |
| WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings(); | |
| WebInspector.View = function() | |
| { | |
| this.element = document.createElement("div"); | |
| this.element.__view = this; | |
| this._visible = true; | |
| this._isRoot = false; | |
| this._isShowing = false; | |
| this._children = []; | |
| this._hideOnDetach = false; | |
| this._cssFiles = []; | |
| } | |
| WebInspector.View._cssFileToVisibleViewCount = {}; | |
| WebInspector.View._cssFileToStyleElement = {}; | |
| WebInspector.View.prototype = { | |
| markAsRoot: function() | |
| { | |
| this._isRoot = true; | |
| }, | |
| isShowing: function() | |
| { | |
| return this._isShowing; | |
| }, | |
| setHideOnDetach: function() | |
| { | |
| this._hideOnDetach = true; | |
| }, | |
| _parentIsShowing: function() | |
| { | |
| return this._isRoot || (this._parentView && this._parentView.isShowing()); | |
| }, | |
| _callOnVisibleChildren: function(method) | |
| { | |
| for (var i = 0; i < this._children.length; ++i) | |
| if (this._children[i]._visible) | |
| method.call(this._children[i]); | |
| }, | |
| _processWillShow: function() | |
| { | |
| this._loadCSSIfNeeded(); | |
| this._callOnVisibleChildren(this._processWillShow); | |
| }, | |
| _processWasShown: function() | |
| { | |
| this._isShowing = true; | |
| this.restoreScrollPositions(); | |
| this.wasShown(); | |
| this.onResize(); | |
| this._callOnVisibleChildren(this._processWasShown); | |
| }, | |
| _processWillHide: function() | |
| { | |
| this.storeScrollPositions(); | |
| this._callOnVisibleChildren(this._processWillHide); | |
| this.willHide(); | |
| this._isShowing = false; | |
| }, | |
| _processWasHidden: function() | |
| { | |
| this._disableCSSIfNeeded(); | |
| this._callOnVisibleChildren(this._processWasHidden); | |
| }, | |
| _processOnResize: function() | |
| { | |
| if (!this.isShowing()) | |
| return; | |
| this.onResize(); | |
| this._callOnVisibleChildren(this._processOnResize); | |
| }, | |
| wasShown: function() | |
| { | |
| }, | |
| willHide: function() | |
| { | |
| }, | |
| onResize: function() | |
| { | |
| }, | |
| show: function(parentElement, insertBefore) | |
| { | |
| WebInspector.View._assert(parentElement, "Attempt to attach view with no parent element"); | |
| if (this.element.parentElement !== parentElement) { | |
| var currentParent = parentElement; | |
| while (currentParent && !currentParent.__view) | |
| currentParent = currentParent.parentElement; | |
| if (currentParent) { | |
| this._parentView = currentParent.__view; | |
| this._parentView._children.push(this); | |
| this._isRoot = false; | |
| } else | |
| WebInspector.View._assert(this._isRoot, "Attempt to attach view to orphan node"); | |
| } else if (this._visible) | |
| return; | |
| this._visible = true; | |
| if (this._parentIsShowing()) | |
| this._processWillShow(); | |
| this.element.addStyleClass("visible"); | |
| if (this.element.parentElement !== parentElement) { | |
| WebInspector.View._incrementViewCounter(parentElement, this.element); | |
| if (insertBefore) | |
| WebInspector.View._originalInsertBefore.call(parentElement, this.element, insertBefore); | |
| else | |
| WebInspector.View._originalAppendChild.call(parentElement, this.element); | |
| } | |
| if (this._parentIsShowing()) | |
| this._processWasShown(); | |
| }, | |
| detach: function(overrideHideOnDetach) | |
| { | |
| var parentElement = this.element.parentElement; | |
| if (!parentElement) | |
| return; | |
| if (this._parentIsShowing()) | |
| this._processWillHide(); | |
| if (this._hideOnDetach && !overrideHideOnDetach) { | |
| this.element.removeStyleClass("visible"); | |
| this._visible = false; | |
| if (this._parentIsShowing()) | |
| this._processWasHidden(); | |
| return; | |
| } | |
| WebInspector.View._decrementViewCounter(parentElement, this.element); | |
| WebInspector.View._originalRemoveChild.call(parentElement, this.element); | |
| this._visible = false; | |
| if (this._parentIsShowing()) | |
| this._processWasHidden(); | |
| if (this._parentView) { | |
| var childIndex = this._parentView._children.indexOf(this); | |
| WebInspector.View._assert(childIndex >= 0, "Attempt to remove non-child view"); | |
| this._parentView._children.splice(childIndex, 1); | |
| this._parentView = null; | |
| } else | |
| WebInspector.View._assert(this._isRoot, "Removing non-root view from DOM"); | |
| }, | |
| detachChildViews: function() | |
| { | |
| var children = this._children.slice(); | |
| for (var i = 0; i < children.length; ++i) | |
| children[i].detach(); | |
| }, | |
| elementsToRestoreScrollPositionsFor: function() | |
| { | |
| return [this.element]; | |
| }, | |
| storeScrollPositions: function() | |
| { | |
| var elements = this.elementsToRestoreScrollPositionsFor(); | |
| for (var i = 0; i < elements.length; ++i) { | |
| var container = elements[i]; | |
| container._scrollTop = container.scrollTop; | |
| container._scrollLeft = container.scrollLeft; | |
| } | |
| }, | |
| restoreScrollPositions: function() | |
| { | |
| var elements = this.elementsToRestoreScrollPositionsFor(); | |
| for (var i = 0; i < elements.length; ++i) { | |
| var container = elements[i]; | |
| if (container._scrollTop) | |
| container.scrollTop = container._scrollTop; | |
| if (container._scrollLeft) | |
| container.scrollLeft = container._scrollLeft; | |
| } | |
| }, | |
| canHighlightLine: function() | |
| { | |
| return false; | |
| }, | |
| highlightLine: function(line) | |
| { | |
| }, | |
| doResize: function() | |
| { | |
| this._processOnResize(); | |
| }, | |
| registerRequiredCSS: function(cssFile) | |
| { | |
| this._cssFiles.push(cssFile); | |
| }, | |
| _loadCSSIfNeeded: function() | |
| { | |
| for (var i = 0; i < this._cssFiles.length; ++i) { | |
| var cssFile = this._cssFiles[i]; | |
| var viewsWithCSSFile = WebInspector.View._cssFileToVisibleViewCount[cssFile]; | |
| WebInspector.View._cssFileToVisibleViewCount[cssFile] = (viewsWithCSSFile || 0) + 1; | |
| if (!viewsWithCSSFile) | |
| this._doLoadCSS(cssFile); | |
| } | |
| }, | |
| _doLoadCSS: function(cssFile) | |
| { | |
| var styleElement = WebInspector.View._cssFileToStyleElement[cssFile]; | |
| if (styleElement) { | |
| styleElement.disabled = false; | |
| return; | |
| } | |
| if (window.debugCSS) { | |
| styleElement = document.createElement("link"); | |
| styleElement.rel = "stylesheet"; | |
| styleElement.type = "text/css"; | |
| styleElement.href = cssFile; | |
| } else { | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("GET", cssFile, false); | |
| xhr.send(null); | |
| styleElement = document.createElement("style"); | |
| styleElement.type = "text/css"; | |
| styleElement.textContent = xhr.responseText; | |
| } | |
| document.head.insertBefore(styleElement, document.head.firstChild); | |
| WebInspector.View._cssFileToStyleElement[cssFile] = styleElement; | |
| }, | |
| _disableCSSIfNeeded: function() | |
| { | |
| for (var i = 0; i < this._cssFiles.length; ++i) { | |
| var cssFile = this._cssFiles[i]; | |
| var viewsWithCSSFile = WebInspector.View._cssFileToVisibleViewCount[cssFile]; | |
| viewsWithCSSFile--; | |
| WebInspector.View._cssFileToVisibleViewCount[cssFile] = viewsWithCSSFile; | |
| if (!viewsWithCSSFile) | |
| this._doUnloadCSS(cssFile); | |
| } | |
| }, | |
| _doUnloadCSS: function(cssFile) | |
| { | |
| var styleElement = WebInspector.View._cssFileToStyleElement[cssFile]; | |
| styleElement.disabled = true; | |
| }, | |
| printViewHierarchy: function() | |
| { | |
| var lines = []; | |
| this._collectViewHierarchy("", lines); | |
| console.log(lines.join("\n")); | |
| }, | |
| _collectViewHierarchy: function(prefix, lines) | |
| { | |
| lines.push(prefix + "[" + this.element.className + "]" + (this._children.length ? " {" : "")); | |
| for (var i = 0; i < this._children.length; ++i) | |
| this._children[i]._collectViewHierarchy(prefix + " ", lines); | |
| if (this._children.length) | |
| lines.push(prefix + "}"); | |
| }, | |
| defaultFocusedElement: function() | |
| { | |
| return this._defaultFocusedElement || this.element; | |
| }, | |
| setDefaultFocusedElement: function(element) | |
| { | |
| this._defaultFocusedElement = element; | |
| }, | |
| focus: function() | |
| { | |
| var element = this.defaultFocusedElement(); | |
| if (!element || element.isAncestor(document.activeElement)) | |
| return; | |
| WebInspector.setCurrentFocusElement(element); | |
| } | |
| } | |
| WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.View._originalAppendChild = Element.prototype.appendChild; | |
| WebInspector.View._originalInsertBefore = Element.prototype.insertBefore; | |
| WebInspector.View._originalRemoveChild = Element.prototype.removeChild; | |
| WebInspector.View._originalRemoveChildren = Element.prototype.removeChildren; | |
| WebInspector.View._incrementViewCounter = function(parentElement, childElement) | |
| { | |
| var count = (childElement.__viewCounter || 0) + (childElement.__view ? 1 : 0); | |
| if (!count) | |
| return; | |
| while (parentElement) { | |
| parentElement.__viewCounter = (parentElement.__viewCounter || 0) + count; | |
| parentElement = parentElement.parentElement; | |
| } | |
| } | |
| WebInspector.View._decrementViewCounter = function(parentElement, childElement) | |
| { | |
| var count = (childElement.__viewCounter || 0) + (childElement.__view ? 1 : 0); | |
| if (!count) | |
| return; | |
| while (parentElement) { | |
| parentElement.__viewCounter -= count; | |
| parentElement = parentElement.parentElement; | |
| } | |
| } | |
| WebInspector.View._assert = function(condition, message) | |
| { | |
| if (!condition) { | |
| console.trace(); | |
| throw new Error(message); | |
| } | |
| } | |
| Element.prototype.appendChild = function(child) | |
| { | |
| WebInspector.View._assert(!child.__view, "Attempt to add view via regular DOM operation."); | |
| return WebInspector.View._originalAppendChild.call(this, child); | |
| } | |
| Element.prototype.insertBefore = function(child, anchor) | |
| { | |
| WebInspector.View._assert(!child.__view, "Attempt to add view via regular DOM operation."); | |
| return WebInspector.View._originalInsertBefore.call(this, child, anchor); | |
| } | |
| Element.prototype.removeChild = function(child) | |
| { | |
| WebInspector.View._assert(!child.__viewCounter && !child.__view, "Attempt to remove element containing view via regular DOM operation"); | |
| return WebInspector.View._originalRemoveChild.call(this, child); | |
| } | |
| Element.prototype.removeChildren = function() | |
| { | |
| WebInspector.View._assert(!this.__viewCounter, "Attempt to remove element containing view via regular DOM operation"); | |
| WebInspector.View._originalRemoveChildren.call(this); | |
| } | |
| WebInspector.HelpScreen = function(title) | |
| { | |
| WebInspector.View.call(this); | |
| this.markAsRoot(); | |
| this.registerRequiredCSS("helpScreen.css"); | |
| this.element.className = "help-window-outer"; | |
| this.element.addEventListener("keydown", this._onKeyDown.bind(this), false); | |
| this.element.tabIndex = 0; | |
| this.element.addEventListener("focus", this._onBlur.bind(this), false); | |
| if (title) { | |
| var mainWindow = this.element.createChild("div", "help-window-main"); | |
| var captionWindow = mainWindow.createChild("div", "help-window-caption"); | |
| captionWindow.appendChild(this._createCloseButton()); | |
| this.contentElement = mainWindow.createChild("div", "help-content"); | |
| captionWindow.createChild("h1", "help-window-title").textContent = title; | |
| } | |
| } | |
| WebInspector.HelpScreen._visibleScreen = null; | |
| WebInspector.HelpScreen.prototype = { | |
| _createCloseButton: function() | |
| { | |
| var closeButton = document.createElement("button"); | |
| closeButton.className = "help-close-button"; | |
| closeButton.textContent = "\u2716"; | |
| closeButton.addEventListener("click", this.hide.bind(this), false); | |
| return closeButton; | |
| }, | |
| showModal: function() | |
| { | |
| var visibleHelpScreen = WebInspector.HelpScreen._visibleScreen; | |
| if (visibleHelpScreen === this) | |
| return; | |
| if (visibleHelpScreen) | |
| visibleHelpScreen.hide(); | |
| WebInspector.HelpScreen._visibleScreen = this; | |
| this.show(document.body); | |
| this.focus(); | |
| }, | |
| hide: function() | |
| { | |
| if (!this.isShowing()) | |
| return; | |
| WebInspector.HelpScreen._visibleScreen = null; | |
| WebInspector.restoreFocusFromElement(this.element); | |
| this.detach(); | |
| }, | |
| isClosingKey: function(keyCode) | |
| { | |
| return [ | |
| WebInspector.KeyboardShortcut.Keys.Enter.code, | |
| WebInspector.KeyboardShortcut.Keys.Esc.code, | |
| WebInspector.KeyboardShortcut.Keys.Space.code, | |
| ].indexOf(keyCode) >= 0; | |
| }, | |
| _onKeyDown: function(event) | |
| { | |
| if (this.isShowing() && this.isClosingKey(event.keyCode)) { | |
| this.hide(); | |
| event.consume(); | |
| } | |
| }, | |
| _onBlur: function(event) | |
| { | |
| if (this.isShowing() && !this.element.isSelfOrAncestor(event.target)) | |
| WebInspector.setCurrentFocusElement(this.element); | |
| } | |
| } | |
| WebInspector.HelpScreen.prototype.__proto__ = WebInspector.View.prototype; | |
| if (!window.InspectorFrontendHost) { | |
| WebInspector.InspectorFrontendHostStub = function() | |
| { | |
| this._attachedWindowHeight = 0; | |
| this.isStub = true; | |
| WebInspector.documentCopyEventFired = this.documentCopy.bind(this); | |
| } | |
| WebInspector.InspectorFrontendHostStub.prototype = { | |
| platform: function() | |
| { | |
| var match = navigator.userAgent.match(/Windows NT/); | |
| if (match) | |
| return "windows"; | |
| match = navigator.userAgent.match(/Mac OS X/); | |
| if (match) | |
| return "mac"; | |
| return "linux"; | |
| }, | |
| port: function() | |
| { | |
| return "unknown"; | |
| }, | |
| bringToFront: function() | |
| { | |
| this._windowVisible = true; | |
| }, | |
| closeWindow: function() | |
| { | |
| this._windowVisible = false; | |
| }, | |
| requestAttachWindow: function() | |
| { | |
| }, | |
| requestDetachWindow: function() | |
| { | |
| }, | |
| requestSetDockSide: function() | |
| { | |
| }, | |
| setAttachedWindowHeight: function(height) | |
| { | |
| }, | |
| moveWindowBy: function(x, y) | |
| { | |
| }, | |
| setInjectedScriptForOrigin: function(origin, script) | |
| { | |
| }, | |
| loaded: function() | |
| { | |
| }, | |
| localizedStringsURL: function() | |
| { | |
| return undefined; | |
| }, | |
| hiddenPanels: function() | |
| { | |
| return WebInspector.queryParamsObject["hiddenPanels"] || ""; | |
| }, | |
| inspectedURLChanged: function(url) | |
| { | |
| document.title = WebInspector.UIString(Preferences.applicationTitle, url); | |
| }, | |
| documentCopy: function(event) | |
| { | |
| if (!this._textToCopy) | |
| return; | |
| event.clipboardData.setData("text", this._textToCopy); | |
| event.preventDefault(); | |
| delete this._textToCopy; | |
| }, | |
| copyText: function(text) | |
| { | |
| this._textToCopy = text; | |
| if (!document.execCommand("copy")) { | |
| var screen = new WebInspector.ClipboardAccessDeniedScreen(); | |
| screen.showModal(); | |
| } | |
| }, | |
| openInNewTab: function(url) | |
| { | |
| window.open(url, "_blank"); | |
| }, | |
| canSave: function() | |
| { | |
| return true; | |
| }, | |
| save: function(url, content, forceSaveAs) | |
| { | |
| var builder = new WebKitBlobBuilder(); | |
| builder.append(content); | |
| var blob = builder.getBlob("application/octet-stream"); | |
| var fr = new FileReader(); | |
| fr.onload = function(e) { | |
| window.location = this.result; | |
| } | |
| fr.readAsDataURL(blob); | |
| }, | |
| canAppend: function() | |
| { | |
| return false; | |
| }, | |
| append: function(url, content) | |
| { | |
| }, | |
| sendMessageToBackend: function(message) | |
| { | |
| }, | |
| recordActionTaken: function(actionCode) | |
| { | |
| }, | |
| recordPanelShown: function(panelCode) | |
| { | |
| }, | |
| recordSettingChanged: function(settingCode) | |
| { | |
| }, | |
| loadResourceSynchronously: function(url) | |
| { | |
| return loadXHR(url); | |
| }, | |
| setZoomFactor: function(zoom) | |
| { | |
| }, | |
| canInspectWorkers: function() | |
| { | |
| return true; | |
| } | |
| } | |
| InspectorFrontendHost = new WebInspector.InspectorFrontendHostStub(); | |
| Preferences.localizeUI = false; | |
| WebInspector.clipboardAccessDeniedMessage = function() | |
| { | |
| return ""; | |
| } | |
| WebInspector.ClipboardAccessDeniedScreen = function() | |
| { | |
| WebInspector.HelpScreen.call(this, WebInspector.UIString("Clipboard access is denied")); | |
| var platformMessage = WebInspector.clipboardAccessDeniedMessage(); | |
| if (platformMessage) { | |
| var p = this.contentElement.createChild("p"); | |
| p.addStyleClass("help-section"); | |
| p.textContent = platformMessage; | |
| } | |
| } | |
| WebInspector.ClipboardAccessDeniedScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype; | |
| } | |
| WebInspector.FileManager = function() | |
| { | |
| } | |
| WebInspector.FileManager.EventTypes = { | |
| SavedURL: "SavedURL", | |
| AppendedToURL: "AppendedToURL" | |
| } | |
| WebInspector.FileManager.prototype = { | |
| canSave: function() | |
| { | |
| return InspectorFrontendHost.canSave(); | |
| }, | |
| canAppend: function() | |
| { | |
| return InspectorFrontendHost.canSave() && ("append" in InspectorFrontendHost); | |
| }, | |
| save: function(url, content, forceSaveAs) | |
| { | |
| var savedURLs = WebInspector.settings.savedURLs.get(); | |
| delete savedURLs[url]; | |
| WebInspector.settings.savedURLs.set(savedURLs); | |
| InspectorFrontendHost.save(url, content, forceSaveAs); | |
| }, | |
| savedURL: function(url) | |
| { | |
| var savedURLs = WebInspector.settings.savedURLs.get(); | |
| savedURLs[url] = true; | |
| WebInspector.settings.savedURLs.set(savedURLs); | |
| this.dispatchEventToListeners(WebInspector.FileManager.EventTypes.SavedURL, url); | |
| }, | |
| isURLSaved: function(url) | |
| { | |
| var savedURLs = WebInspector.settings.savedURLs.get(); | |
| return savedURLs[url]; | |
| }, | |
| append: function(url, content) | |
| { | |
| InspectorFrontendHost.append(url, content); | |
| }, | |
| appendedToURL: function(url) | |
| { | |
| this.dispatchEventToListeners(WebInspector.FileManager.EventTypes.AppendedToURL, url); | |
| } | |
| } | |
| WebInspector.FileManager.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.fileManager = new WebInspector.FileManager(); | |
| WebInspector.Checkbox = function(label, className, tooltip) | |
| { | |
| this.element = document.createElement('label'); | |
| this._inputElement = document.createElement('input'); | |
| this._inputElement.type = "checkbox"; | |
| this.element.className = className; | |
| this.element.appendChild(this._inputElement); | |
| this.element.appendChild(document.createTextNode(label)); | |
| if (tooltip) | |
| this.element.title = tooltip; | |
| } | |
| WebInspector.Checkbox.prototype = { | |
| set checked(checked) | |
| { | |
| this._inputElement.checked = checked; | |
| }, | |
| get checked() | |
| { | |
| return this._inputElement.checked; | |
| }, | |
| addEventListener: function(listener) | |
| { | |
| function listenerWrapper(event) | |
| { | |
| if (listener) | |
| listener(event); | |
| event.consume(); | |
| return true; | |
| } | |
| this._inputElement.addEventListener("click", listenerWrapper, false); | |
| this.element.addEventListener("click", listenerWrapper, false); | |
| } | |
| } | |
| WebInspector.ContextMenuItem = function(topLevelMenu, type, label, disabled, checked) | |
| { | |
| this._type = type; | |
| this._label = label; | |
| this._disabled = disabled; | |
| this._checked = checked; | |
| this._contextMenu = topLevelMenu; | |
| if (type === "item" || type === "checkbox") | |
| this._id = topLevelMenu.nextId(); | |
| } | |
| WebInspector.ContextMenuItem.prototype = { | |
| id: function() | |
| { | |
| return this._id; | |
| }, | |
| type: function() | |
| { | |
| return this._type; | |
| }, | |
| _buildDescriptor: function() | |
| { | |
| switch (this._type) { | |
| case "item": | |
| return { type: "item", id: this._id, label: this._label, enabled: !this._disabled }; | |
| case "separator": | |
| return { type: "separator" }; | |
| case "checkbox": | |
| return { type: "checkbox", id: this._id, label: this._label, checked: !!this._checked, enabled: !this._disabled }; | |
| } | |
| } | |
| } | |
| WebInspector.ContextSubMenuItem = function(topLevelMenu, label, disabled) | |
| { | |
| WebInspector.ContextMenuItem.call(this, topLevelMenu, "subMenu", label, disabled); | |
| this._items = []; | |
| } | |
| WebInspector.ContextSubMenuItem.prototype = { | |
| appendItem: function(label, handler, disabled) | |
| { | |
| var item = new WebInspector.ContextMenuItem(this._contextMenu, "item", label, disabled); | |
| this._pushItem(item); | |
| this._contextMenu._setHandler(item.id(), handler); | |
| return item; | |
| }, | |
| appendSubMenuItem: function(label, disabled) | |
| { | |
| var item = new WebInspector.ContextSubMenuItem(this._contextMenu, label, disabled); | |
| this._pushItem(item); | |
| return item; | |
| }, | |
| appendCheckboxItem: function(label, handler, checked, disabled) | |
| { | |
| var item = new WebInspector.ContextMenuItem(this._contextMenu, "checkbox", label, disabled, checked); | |
| this._pushItem(item); | |
| this._contextMenu._setHandler(item.id(), handler); | |
| return item; | |
| }, | |
| appendSeparator: function() | |
| { | |
| if (this._items.length) | |
| this._pendingSeparator = true; | |
| }, | |
| _pushItem: function(item) | |
| { | |
| if (this._pendingSeparator) { | |
| this._items.push(new WebInspector.ContextMenuItem(this._contextMenu, "separator")); | |
| delete this._pendingSeparator; | |
| } | |
| this._items.push(item); | |
| }, | |
| isEmpty: function() | |
| { | |
| return !this._items.length; | |
| }, | |
| _buildDescriptor: function() | |
| { | |
| var result = { type: "subMenu", label: this._label, enabled: !this._disabled, subItems: [] }; | |
| for (var i = 0; i < this._items.length; ++i) | |
| result.subItems.push(this._items[i]._buildDescriptor()); | |
| return result; | |
| } | |
| } | |
| WebInspector.ContextSubMenuItem.prototype.__proto__ = WebInspector.ContextMenuItem.prototype; | |
| WebInspector.ContextMenu = function() { | |
| WebInspector.ContextSubMenuItem.call(this, this, ""); | |
| this._handlers = {}; | |
| this._id = 0; | |
| } | |
| WebInspector.ContextMenu.prototype = { | |
| nextId: function() | |
| { | |
| return this._id++; | |
| }, | |
| show: function(event) | |
| { | |
| var menuObject = this._buildDescriptor(); | |
| if (menuObject.length) { | |
| WebInspector._contextMenu = this; | |
| InspectorFrontendHost.showContextMenu(event, menuObject); | |
| } | |
| event.consume(); | |
| }, | |
| _setHandler: function(id, handler) | |
| { | |
| if (handler) | |
| this._handlers[id] = handler; | |
| }, | |
| _buildDescriptor: function() | |
| { | |
| var result = []; | |
| for (var i = 0; i < this._items.length; ++i) | |
| result.push(this._items[i]._buildDescriptor()); | |
| return result; | |
| }, | |
| _itemSelected: function(id) | |
| { | |
| if (this._handlers[id]) | |
| this._handlers[id].call(this); | |
| }, | |
| appendApplicableItems: function(target) | |
| { | |
| for (var i = 0; i < WebInspector.ContextMenu._providers.length; ++i) { | |
| var provider = WebInspector.ContextMenu._providers[i]; | |
| this.appendSeparator(); | |
| provider.appendApplicableItems(this, target); | |
| this.appendSeparator(); | |
| } | |
| } | |
| } | |
| WebInspector.ContextMenu.prototype.__proto__ = WebInspector.ContextSubMenuItem.prototype; | |
| WebInspector.ContextMenu.Provider = function() { | |
| } | |
| WebInspector.ContextMenu.Provider.prototype = { | |
| appendApplicableItems: function(contextMenu, target) { } | |
| } | |
| WebInspector.ContextMenu.registerProvider = function(provider) | |
| { | |
| WebInspector.ContextMenu._providers.push(provider); | |
| } | |
| WebInspector.ContextMenu._providers = []; | |
| WebInspector.contextMenuItemSelected = function(id) | |
| { | |
| if (WebInspector._contextMenu) | |
| WebInspector._contextMenu._itemSelected(id); | |
| } | |
| WebInspector.contextMenuCleared = function() | |
| { | |
| } | |
| if (!InspectorFrontendHost.showContextMenu) { | |
| WebInspector.SoftContextMenu = function(items, parentMenu) | |
| { | |
| this._items = items; | |
| this._parentMenu = parentMenu; | |
| } | |
| WebInspector.SoftContextMenu.prototype = { | |
| show: function(event) | |
| { | |
| this._x = event.x; | |
| this._y = event.y; | |
| this._time = new Date().getTime(); | |
| var absoluteX = event.pageX; | |
| var absoluteY = event.pageY; | |
| var targetElement = event.target; | |
| while (targetElement && window !== targetElement.ownerDocument.defaultView) { | |
| var frameElement = targetElement.ownerDocument.defaultView.frameElement; | |
| absoluteY += frameElement.totalOffsetTop(); | |
| absoluteX += frameElement.totalOffsetLeft(); | |
| targetElement = frameElement; | |
| } | |
| this._contextMenuElement = document.createElement("div"); | |
| this._contextMenuElement.className = "soft-context-menu"; | |
| this._contextMenuElement.tabIndex = 0; | |
| this._contextMenuElement.style.top = absoluteY + "px"; | |
| this._contextMenuElement.style.left = absoluteX + "px"; | |
| this._contextMenuElement.addEventListener("mouseup", consumeEvent, false); | |
| this._contextMenuElement.addEventListener("keydown", this._menuKeyDown.bind(this), false); | |
| for (var i = 0; i < this._items.length; ++i) | |
| this._contextMenuElement.appendChild(this._createMenuItem(this._items[i])); | |
| if (!this._parentMenu) { | |
| this._glassPaneElement = document.createElement("div"); | |
| this._glassPaneElement.className = "soft-context-menu-glass-pane"; | |
| this._glassPaneElement.tabIndex = 0; | |
| this._glassPaneElement.addEventListener("mouseup", this._glassPaneMouseUp.bind(this), false); | |
| this._glassPaneElement.appendChild(this._contextMenuElement); | |
| document.body.appendChild(this._glassPaneElement); | |
| this._focus(); | |
| } else | |
| this._parentMenu._parentGlassPaneElement().appendChild(this._contextMenuElement); | |
| if (document.body.offsetWidth < this._contextMenuElement.offsetLeft + this._contextMenuElement.offsetWidth) | |
| this._contextMenuElement.style.left = (absoluteX - this._contextMenuElement.offsetWidth) + "px"; | |
| if (document.body.offsetHeight < this._contextMenuElement.offsetTop + this._contextMenuElement.offsetHeight) | |
| this._contextMenuElement.style.top = (document.body.offsetHeight - this._contextMenuElement.offsetHeight) + "px"; | |
| event.consume(true); | |
| }, | |
| _parentGlassPaneElement: function() | |
| { | |
| if (this._glassPaneElement) | |
| return this._glassPaneElement; | |
| if (this._parentMenu) | |
| return this._parentMenu._parentGlassPaneElement(); | |
| return null; | |
| }, | |
| _createMenuItem: function(item) | |
| { | |
| if (item.type === "separator") | |
| return this._createSeparator(); | |
| if (item.type === "subMenu") | |
| return this._createSubMenu(item); | |
| var menuItemElement = document.createElement("div"); | |
| menuItemElement.className = "soft-context-menu-item"; | |
| var checkMarkElement = document.createElement("span"); | |
| checkMarkElement.textContent = "\u2713 "; | |
| checkMarkElement.className = "soft-context-menu-item-checkmark"; | |
| if (!item.checked) | |
| checkMarkElement.style.opacity = "0"; | |
| menuItemElement.appendChild(checkMarkElement); | |
| menuItemElement.appendChild(document.createTextNode(item.label)); | |
| menuItemElement.addEventListener("mousedown", this._menuItemMouseDown.bind(this), false); | |
| menuItemElement.addEventListener("mouseup", this._menuItemMouseUp.bind(this), false); | |
| menuItemElement.addEventListener("mouseover", this._menuItemMouseOver.bind(this), false); | |
| menuItemElement.addEventListener("mouseout", this._menuItemMouseOut.bind(this), false); | |
| menuItemElement._actionId = item.id; | |
| return menuItemElement; | |
| }, | |
| _createSubMenu: function(item) | |
| { | |
| var menuItemElement = document.createElement("div"); | |
| menuItemElement.className = "soft-context-menu-item"; | |
| menuItemElement._subItems = item.subItems; | |
| var checkMarkElement = document.createElement("span"); | |
| checkMarkElement.textContent = "\u2713 "; | |
| checkMarkElement.className = "soft-context-menu-item-checkmark"; | |
| checkMarkElement.style.opacity = "0"; | |
| menuItemElement.appendChild(checkMarkElement); | |
| var subMenuArrowElement = document.createElement("span"); | |
| subMenuArrowElement.textContent = "\u25B6"; | |
| subMenuArrowElement.className = "soft-context-menu-item-submenu-arrow"; | |
| menuItemElement.appendChild(document.createTextNode(item.label)); | |
| menuItemElement.appendChild(subMenuArrowElement); | |
| menuItemElement.addEventListener("mousedown", this._menuItemMouseDown.bind(this), false); | |
| menuItemElement.addEventListener("mouseup", this._menuItemMouseUp.bind(this), false); | |
| menuItemElement.addEventListener("mouseover", this._menuItemMouseOver.bind(this), false); | |
| menuItemElement.addEventListener("mouseout", this._menuItemMouseOut.bind(this), false); | |
| return menuItemElement; | |
| }, | |
| _createSeparator: function() | |
| { | |
| var separatorElement = document.createElement("div"); | |
| separatorElement.className = "soft-context-menu-separator"; | |
| separatorElement._isSeparator = true; | |
| separatorElement.addEventListener("mouseover", this._hideSubMenu.bind(this), false); | |
| separatorElement.createChild("div", "separator-line"); | |
| return separatorElement; | |
| }, | |
| _menuItemMouseDown: function(event) | |
| { | |
| event.consume(true); | |
| }, | |
| _menuItemMouseUp: function(event) | |
| { | |
| this._triggerAction(event.target, event); | |
| event.consume(); | |
| }, | |
| _focus: function() | |
| { | |
| this._contextMenuElement.focus(); | |
| }, | |
| _triggerAction: function(menuItemElement, event) | |
| { | |
| if (!menuItemElement._subItems) { | |
| this._discardMenu(true, event); | |
| if (typeof menuItemElement._actionId !== "undefined") { | |
| WebInspector.contextMenuItemSelected(menuItemElement._actionId); | |
| delete menuItemElement._actionId; | |
| } | |
| return; | |
| } | |
| this._showSubMenu(menuItemElement, event); | |
| event.consume(); | |
| }, | |
| _showSubMenu: function(menuItemElement, event) | |
| { | |
| if (menuItemElement._subMenuTimer) { | |
| clearTimeout(menuItemElement._subMenuTimer); | |
| delete menuItemElement._subMenuTimer; | |
| } | |
| if (this._subMenu) | |
| return; | |
| this._subMenu = new WebInspector.SoftContextMenu(menuItemElement._subItems, this); | |
| this._subMenu.show(this._buildMouseEventForSubMenu(menuItemElement)); | |
| }, | |
| _buildMouseEventForSubMenu: function(subMenuItemElement) | |
| { | |
| var subMenuOffset = { x: subMenuItemElement.offsetWidth - 3, y: subMenuItemElement.offsetTop - 1 }; | |
| var targetX = this._x + subMenuOffset.x; | |
| var targetY = this._y + subMenuOffset.y; | |
| var targetPageX = parseInt(this._contextMenuElement.style.left, 10) + subMenuOffset.x; | |
| var targetPageY = parseInt(this._contextMenuElement.style.top, 10) + subMenuOffset.y; | |
| return { x: targetX, y: targetY, pageX: targetPageX, pageY: targetPageY, consume: function() {} }; | |
| }, | |
| _hideSubMenu: function() | |
| { | |
| if (!this._subMenu) | |
| return; | |
| this._subMenu._discardSubMenus(); | |
| this._focus(); | |
| }, | |
| _menuItemMouseOver: function(event) | |
| { | |
| this._highlightMenuItem(event.target); | |
| }, | |
| _menuItemMouseOut: function(event) | |
| { | |
| if (!this._subMenu || !event.relatedTarget) { | |
| this._highlightMenuItem(null); | |
| return; | |
| } | |
| var relatedTarget = event.relatedTarget; | |
| if (this._contextMenuElement.isSelfOrAncestor(relatedTarget) || relatedTarget.hasStyleClass("soft-context-menu-glass-pane")) | |
| this._highlightMenuItem(null); | |
| }, | |
| _highlightMenuItem: function(menuItemElement) | |
| { | |
| if (this._highlightedMenuItemElement === menuItemElement) | |
| return; | |
| this._hideSubMenu(); | |
| if (this._highlightedMenuItemElement) { | |
| this._highlightedMenuItemElement.removeStyleClass("soft-context-menu-item-mouse-over"); | |
| if (this._highlightedMenuItemElement._subItems && this._highlightedMenuItemElement._subMenuTimer) { | |
| clearTimeout(this._highlightedMenuItemElement._subMenuTimer); | |
| delete this._highlightedMenuItemElement._subMenuTimer; | |
| } | |
| } | |
| this._highlightedMenuItemElement = menuItemElement; | |
| if (this._highlightedMenuItemElement) { | |
| this._highlightedMenuItemElement.addStyleClass("soft-context-menu-item-mouse-over"); | |
| this._contextMenuElement.focus(); | |
| if (this._highlightedMenuItemElement._subItems && !this._highlightedMenuItemElement._subMenuTimer) | |
| this._highlightedMenuItemElement._subMenuTimer = setTimeout(this._showSubMenu.bind(this, this._highlightedMenuItemElement, this._buildMouseEventForSubMenu(this._highlightedMenuItemElement)), 150); | |
| } | |
| }, | |
| _highlightPrevious: function() | |
| { | |
| var menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.previousSibling : this._contextMenuElement.lastChild; | |
| while (menuItemElement && menuItemElement._isSeparator) | |
| menuItemElement = menuItemElement.previousSibling; | |
| if (menuItemElement) | |
| this._highlightMenuItem(menuItemElement); | |
| }, | |
| _highlightNext: function() | |
| { | |
| var menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.nextSibling : this._contextMenuElement.firstChild; | |
| while (menuItemElement && menuItemElement._isSeparator) | |
| menuItemElement = menuItemElement.nextSibling; | |
| if (menuItemElement) | |
| this._highlightMenuItem(menuItemElement); | |
| }, | |
| _menuKeyDown: function(event) | |
| { | |
| switch (event.keyIdentifier) { | |
| case "Up": | |
| this._highlightPrevious(); break; | |
| case "Down": | |
| this._highlightNext(); break; | |
| case "Left": | |
| if (this._parentMenu) { | |
| this._highlightMenuItem(null); | |
| this._parentMenu._focus(); | |
| } | |
| break; | |
| case "Right": | |
| if (!this._highlightedMenuItemElement) | |
| break; | |
| if (this._highlightedMenuItemElement._subItems) { | |
| this._showSubMenu(this._highlightedMenuItemElement, this._buildMouseEventForSubMenu(this._highlightedMenuItemElement)); | |
| this._subMenu._focus(); | |
| this._subMenu._highlightNext(); | |
| } | |
| break; | |
| case "U+001B": | |
| this._discardMenu(true, event); break; | |
| case "Enter": | |
| if (!isEnterKey(event)) | |
| break; | |
| case "U+0020": | |
| if (this._highlightedMenuItemElement) | |
| this._triggerAction(this._highlightedMenuItemElement, event); | |
| break; | |
| } | |
| event.consume(true); | |
| }, | |
| _glassPaneMouseUp: function(event) | |
| { | |
| if (event.x === this._x && event.y === this._y && new Date().getTime() - this._time < 300) | |
| return; | |
| this._discardMenu(true, event); | |
| event.consume(); | |
| }, | |
| _discardMenu: function(closeParentMenus, event) | |
| { | |
| if (this._subMenu && !closeParentMenus) | |
| return; | |
| if (this._glassPaneElement) { | |
| var glassPane = this._glassPaneElement; | |
| delete this._glassPaneElement; | |
| document.body.removeChild(glassPane); | |
| if (this._parentMenu) { | |
| delete this._parentMenu._subMenu; | |
| if (closeParentMenus) | |
| this._parentMenu._discardMenu(closeParentMenus, event); | |
| } | |
| if (event) | |
| event.consume(true); | |
| } else if (this._parentMenu && this._contextMenuElement.parentElement) { | |
| this._discardSubMenus(); | |
| if (closeParentMenus) | |
| this._parentMenu._discardMenu(closeParentMenus, event); | |
| if (event) | |
| event.consume(true); | |
| } | |
| }, | |
| _discardSubMenus: function() | |
| { | |
| if (this._subMenu) | |
| this._subMenu._discardSubMenus(); | |
| if (this._contextMenuElement.parentElement) | |
| this._contextMenuElement.parentElement.removeChild(this._contextMenuElement); | |
| if (this._parentMenu) | |
| delete this._parentMenu._subMenu; | |
| } | |
| } | |
| InspectorFrontendHost.showContextMenu = function(event, items) | |
| { | |
| new WebInspector.SoftContextMenu(items).show(event); | |
| } | |
| } | |
| WebInspector.KeyboardShortcut = function() | |
| { | |
| } | |
| WebInspector.KeyboardShortcut.Modifiers = { | |
| None: 0, | |
| Shift: 1, | |
| Ctrl: 2, | |
| Alt: 4, | |
| Meta: 8, | |
| get CtrlOrMeta() | |
| { | |
| return WebInspector.isMac() ? this.Meta : this.Ctrl; | |
| } | |
| }; | |
| WebInspector.KeyboardShortcut.Keys = { | |
| Backspace: { code: 8, name: "\u21a4" }, | |
| Tab: { code: 9, name: { mac: "\u21e5", other: "<Tab>" } }, | |
| Enter: { code: 13, name: { mac: "\u21a9", other: "<Enter>" } }, | |
| Esc: { code: 27, name: { mac: "\u238b", other: "<Esc>" } }, | |
| Space: { code: 32, name: "<Space>" }, | |
| PageUp: { code: 33, name: { mac: "\u21de", other: "<PageUp>" } }, | |
| PageDown: { code: 34, name: { mac: "\u21df", other: "<PageDown>" } }, | |
| End: { code: 35, name: { mac: "\u2197", other: "<End>" } }, | |
| Home: { code: 36, name: { mac: "\u2196", other: "<Home>" } }, | |
| Left: { code: 37, name: "<Left>" }, | |
| Up: { code: 38, name: "<Up>" }, | |
| Right: { code: 39, name: "<Right>" }, | |
| Down: { code: 40, name: "<Down>" }, | |
| Delete: { code: 46, name: "<Del>" }, | |
| Zero: { code: 48, name: "0" }, | |
| F1: { code: 112, name: "F1" }, | |
| F2: { code: 113, name: "F2" }, | |
| F3: { code: 114, name: "F3" }, | |
| F4: { code: 115, name: "F4" }, | |
| F5: { code: 116, name: "F5" }, | |
| F6: { code: 117, name: "F6" }, | |
| F7: { code: 118, name: "F7" }, | |
| F8: { code: 119, name: "F8" }, | |
| F9: { code: 120, name: "F9" }, | |
| F10: { code: 121, name: "F10" }, | |
| F11: { code: 122, name: "F11" }, | |
| F12: { code: 123, name: "F12" }, | |
| Semicolon: { code: 186, name: ";" }, | |
| Plus: { code: 187, name: "+" }, | |
| Comma: { code: 188, name: "," }, | |
| Minus: { code: 189, name: "-" }, | |
| Period: { code: 190, name: "." }, | |
| Slash: { code: 191, name: "/" }, | |
| Apostrophe: { code: 192, name: "`" }, | |
| SingleQuote: { code: 222, name: "\'" } | |
| }; | |
| WebInspector.KeyboardShortcut.makeKey = function(keyCode, modifiers) | |
| { | |
| if (typeof keyCode === "string") | |
| keyCode = keyCode.charCodeAt(0) - 32; | |
| modifiers = modifiers || WebInspector.KeyboardShortcut.Modifiers.None; | |
| return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers); | |
| } | |
| WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent) | |
| { | |
| var modifiers = WebInspector.KeyboardShortcut.Modifiers.None; | |
| if (keyboardEvent.shiftKey) | |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift; | |
| if (keyboardEvent.ctrlKey) | |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl; | |
| if (keyboardEvent.altKey) | |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt; | |
| if (keyboardEvent.metaKey) | |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta; | |
| return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyboardEvent.keyCode, modifiers); | |
| } | |
| WebInspector.KeyboardShortcut.eventHasCtrlOrMeta = function(event) | |
| { | |
| return WebInspector.isMac() ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey; | |
| } | |
| WebInspector.KeyboardShortcut.makeDescriptor = function(key, modifiers) | |
| { | |
| return { | |
| key: WebInspector.KeyboardShortcut.makeKey(typeof key === "string" ? key : key.code, modifiers), | |
| name: WebInspector.KeyboardShortcut.shortcutToString(key, modifiers) | |
| }; | |
| } | |
| WebInspector.KeyboardShortcut.shortcutToString = function(key, modifiers) | |
| { | |
| return WebInspector.KeyboardShortcut._modifiersToString(modifiers) + WebInspector.KeyboardShortcut._keyName(key); | |
| } | |
| WebInspector.KeyboardShortcut._keyName = function(key) | |
| { | |
| if (typeof key === "string") | |
| return key.toUpperCase(); | |
| if (typeof key.name === "string") | |
| return key.name; | |
| return key.name[WebInspector.platform()] || key.name.other; | |
| } | |
| WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers) | |
| { | |
| return (keyCode & 255) | (modifiers << 8); | |
| }; | |
| WebInspector.KeyboardShortcut._modifiersToString = function(modifiers) | |
| { | |
| const cmdKey = "\u2318"; | |
| const optKey = "\u2325"; | |
| const shiftKey = "\u21e7"; | |
| const ctrlKey = "\u2303"; | |
| var isMac = WebInspector.isMac(); | |
| var res = ""; | |
| if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Ctrl) | |
| res += isMac ? ctrlKey : "<Ctrl> + "; | |
| if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Alt) | |
| res += isMac ? optKey : "<Alt> + "; | |
| if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Shift) | |
| res += isMac ? shiftKey : "<Shift> + "; | |
| if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Meta) | |
| res += isMac ? cmdKey : "<Win> + "; | |
| return res; | |
| }; | |
| WebInspector.TextPrompt = function(completions, stopCharacters) | |
| { | |
| this._proxyElement; | |
| this._proxyElementDisplay = "inline-block"; | |
| this._loadCompletions = completions; | |
| this._completionStopCharacters = stopCharacters; | |
| this._suggestForceable = true; | |
| } | |
| WebInspector.TextPrompt.Events = { | |
| ItemApplied: "text-prompt-item-applied", | |
| ItemAccepted: "text-prompt-item-accepted" | |
| }; | |
| WebInspector.TextPrompt.prototype = { | |
| get proxyElement() | |
| { | |
| return this._proxyElement; | |
| }, | |
| setSuggestForceable: function(x) | |
| { | |
| this._suggestForceable = x; | |
| }, | |
| setSuggestBoxEnabled: function(className) | |
| { | |
| this._suggestBoxClassName = className; | |
| }, | |
| renderAsBlock: function() | |
| { | |
| this._proxyElementDisplay = "block"; | |
| }, | |
| attach: function(element) | |
| { | |
| return this._attachInternal(element); | |
| }, | |
| attachAndStartEditing: function(element, blurListener) | |
| { | |
| this._attachInternal(element); | |
| this._startEditing(blurListener); | |
| return this.proxyElement; | |
| }, | |
| _attachInternal: function(element) | |
| { | |
| if (this.proxyElement) | |
| throw "Cannot attach an attached TextPrompt"; | |
| this._element = element; | |
| this._boundOnKeyDown = this.onKeyDown.bind(this); | |
| this._boundOnMouseWheel = this.onMouseWheel.bind(this); | |
| this._boundSelectStart = this._selectStart.bind(this); | |
| this._proxyElement = element.ownerDocument.createElement("span"); | |
| this._proxyElement.style.display = this._proxyElementDisplay; | |
| element.parentElement.insertBefore(this.proxyElement, element); | |
| this.proxyElement.appendChild(element); | |
| this._element.addStyleClass("text-prompt"); | |
| this._element.addEventListener("keydown", this._boundOnKeyDown, false); | |
| this._element.addEventListener("mousewheel", this._boundOnMouseWheel, false); | |
| this._element.addEventListener("selectstart", this._boundSelectStart, false); | |
| if (typeof this._suggestBoxClassName === "string") | |
| this._suggestBox = new WebInspector.TextPrompt.SuggestBox(this, this._element, this._suggestBoxClassName); | |
| return this.proxyElement; | |
| }, | |
| detach: function() | |
| { | |
| this._removeFromElement(); | |
| this.proxyElement.parentElement.insertBefore(this._element, this.proxyElement); | |
| this.proxyElement.parentElement.removeChild(this.proxyElement); | |
| this._element.removeStyleClass("text-prompt"); | |
| this._element.removeEventListener("keydown", this._boundOnKeyDown, false); | |
| this._element.removeEventListener("mousewheel", this._boundOnMouseWheel, false); | |
| this._element.removeEventListener("selectstart", this._boundSelectStart, false); | |
| delete this._proxyElement; | |
| WebInspector.restoreFocusFromElement(this._element); | |
| }, | |
| get text() | |
| { | |
| return this._element.textContent; | |
| }, | |
| set text(x) | |
| { | |
| this._removeSuggestionAids(); | |
| if (!x) { | |
| this._element.removeChildren(); | |
| this._element.appendChild(document.createElement("br")); | |
| } else | |
| this._element.textContent = x; | |
| this.moveCaretToEndOfPrompt(); | |
| this._element.scrollIntoView(); | |
| }, | |
| _removeFromElement: function() | |
| { | |
| this.clearAutoComplete(true); | |
| this._element.removeEventListener("keydown", this._boundOnKeyDown, false); | |
| this._element.removeEventListener("selectstart", this._boundSelectStart, false); | |
| if (this._isEditing) | |
| this._stopEditing(); | |
| if (this._suggestBox) | |
| this._suggestBox.removeFromElement(); | |
| }, | |
| _startEditing: function(blurListener) | |
| { | |
| this._isEditing = true; | |
| this._element.addStyleClass("editing"); | |
| if (blurListener) { | |
| this._blurListener = blurListener; | |
| this._element.addEventListener("blur", this._blurListener, false); | |
| } | |
| this._oldTabIndex = this._element.tabIndex; | |
| if (this._element.tabIndex < 0) | |
| this._element.tabIndex = 0; | |
| WebInspector.setCurrentFocusElement(this._element); | |
| }, | |
| _stopEditing: function() | |
| { | |
| this._element.tabIndex = this._oldTabIndex; | |
| if (this._blurListener) | |
| this._element.removeEventListener("blur", this._blurListener, false); | |
| this._element.removeStyleClass("editing"); | |
| delete this._isEditing; | |
| }, | |
| _removeSuggestionAids: function() | |
| { | |
| this.clearAutoComplete(); | |
| this.hideSuggestBox(); | |
| }, | |
| _selectStart: function(event) | |
| { | |
| if (this._selectionTimeout) | |
| clearTimeout(this._selectionTimeout); | |
| this._removeSuggestionAids(); | |
| function moveBackIfOutside() | |
| { | |
| delete this._selectionTimeout; | |
| if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed) { | |
| this.moveCaretToEndOfPrompt(); | |
| this.autoCompleteSoon(); | |
| } | |
| } | |
| this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); | |
| }, | |
| defaultKeyHandler: function(event, force) | |
| { | |
| this.clearAutoComplete(); | |
| this.autoCompleteSoon(force); | |
| return false; | |
| }, | |
| onMouseWheel: function(event) | |
| { | |
| }, | |
| onKeyDown: function(event) | |
| { | |
| var handled = false; | |
| var invokeDefault = true; | |
| switch (event.keyIdentifier) { | |
| case "Up": | |
| handled = this.upKeyPressed(event); | |
| break; | |
| case "Down": | |
| handled = this.downKeyPressed(event); | |
| break; | |
| case "PageUp": | |
| handled = this.pageUpKeyPressed(event); | |
| break; | |
| case "PageDown": | |
| handled = this.pageDownKeyPressed(event); | |
| break; | |
| case "U+0009": | |
| handled = this.tabKeyPressed(event); | |
| break; | |
| case "Enter": | |
| handled = this.enterKeyPressed(event); | |
| break; | |
| case "Left": | |
| case "Home": | |
| this._removeSuggestionAids(); | |
| invokeDefault = false; | |
| break; | |
| case "Right": | |
| case "End": | |
| if (this.isCaretAtEndOfPrompt()) | |
| handled = this.acceptAutoComplete(); | |
| else | |
| this._removeSuggestionAids(); | |
| invokeDefault = false; | |
| break; | |
| case "U+001B": | |
| if (this.isSuggestBoxVisible()) { | |
| this._suggestBox.hide(); | |
| handled = true; | |
| } | |
| break; | |
| case "U+0020": | |
| if (this._suggestForceable && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) { | |
| this.defaultKeyHandler(event, true); | |
| handled = true; | |
| } | |
| break; | |
| case "Alt": | |
| case "Meta": | |
| case "Shift": | |
| case "Control": | |
| invokeDefault = false; | |
| break; | |
| } | |
| if (!handled && invokeDefault) | |
| handled = this.defaultKeyHandler(event); | |
| if (handled) | |
| event.consume(true); | |
| return handled; | |
| }, | |
| acceptAutoComplete: function() | |
| { | |
| var result = false; | |
| if (this.isSuggestBoxVisible()) | |
| result = this._suggestBox.acceptSuggestion(); | |
| if (!result) | |
| result = this.acceptSuggestion(); | |
| return result; | |
| }, | |
| clearAutoComplete: function(includeTimeout) | |
| { | |
| if (includeTimeout && this._completeTimeout) { | |
| clearTimeout(this._completeTimeout); | |
| delete this._completeTimeout; | |
| } | |
| delete this._waitingForCompletions; | |
| if (!this.autoCompleteElement) | |
| return; | |
| if (this.autoCompleteElement.parentNode) | |
| this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement); | |
| delete this.autoCompleteElement; | |
| if (!this._userEnteredRange || !this._userEnteredText) | |
| return; | |
| this._userEnteredRange.deleteContents(); | |
| this._element.pruneEmptyTextNodes(); | |
| var userTextNode = document.createTextNode(this._userEnteredText); | |
| this._userEnteredRange.insertNode(userTextNode); | |
| var selectionRange = document.createRange(); | |
| selectionRange.setStart(userTextNode, this._userEnteredText.length); | |
| selectionRange.setEnd(userTextNode, this._userEnteredText.length); | |
| var selection = window.getSelection(); | |
| selection.removeAllRanges(); | |
| selection.addRange(selectionRange); | |
| delete this._userEnteredRange; | |
| delete this._userEnteredText; | |
| }, | |
| autoCompleteSoon: function(force) | |
| { | |
| var immediately = this.isSuggestBoxVisible() || force; | |
| if (!this._completeTimeout) | |
| this._completeTimeout = setTimeout(this.complete.bind(this, true, force), immediately ? 0 : 250); | |
| }, | |
| complete: function(auto, force, reverse) | |
| { | |
| this.clearAutoComplete(true); | |
| var selection = window.getSelection(); | |
| if (!selection.rangeCount) | |
| return; | |
| var selectionRange = selection.getRangeAt(0); | |
| var isEmptyInput = selectionRange.commonAncestorContainer === this._element; | |
| var shouldExit; | |
| if (auto && isEmptyInput && !force) | |
| shouldExit = true; | |
| else if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this._element)) | |
| shouldExit = true; | |
| else if (auto && !force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible()) | |
| shouldExit = true; | |
| else if (!selection.isCollapsed) | |
| shouldExit = true; | |
| else if (!force) { | |
| var wordSuffixRange = selectionRange.startContainer.rangeOfWord(selectionRange.endOffset, this._completionStopCharacters, this._element, "forward"); | |
| if (wordSuffixRange.toString().length) | |
| shouldExit = true; | |
| } | |
| if (shouldExit) { | |
| this.hideSuggestBox(); | |
| return; | |
| } | |
| var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this._completionStopCharacters, this._element, "backward"); | |
| this._waitingForCompletions = true; | |
| this._loadCompletions(this, wordPrefixRange, force, this._completionsReady.bind(this, selection, auto, wordPrefixRange, !!reverse)); | |
| }, | |
| _boxForAnchorAtStart: function(selection, textRange) | |
| { | |
| var rangeCopy = selection.getRangeAt(0).cloneRange(); | |
| var anchorElement = document.createElement("span"); | |
| anchorElement.textContent = "\u200B"; | |
| textRange.insertNode(anchorElement); | |
| var box = anchorElement.boxInWindow(window); | |
| anchorElement.parentElement.removeChild(anchorElement); | |
| selection.removeAllRanges(); | |
| selection.addRange(rangeCopy); | |
| return box; | |
| }, | |
| _buildCommonPrefix: function(completions, wordPrefixLength) | |
| { | |
| var commonPrefix = completions[0]; | |
| for (var i = 0; i < completions.length; ++i) { | |
| var completion = completions[i]; | |
| var lastIndex = Math.min(commonPrefix.length, completion.length); | |
| for (var j = wordPrefixLength; j < lastIndex; ++j) { | |
| if (commonPrefix[j] !== completion[j]) { | |
| commonPrefix = commonPrefix.substr(0, j); | |
| break; | |
| } | |
| } | |
| } | |
| return commonPrefix; | |
| }, | |
| _completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions) | |
| { | |
| if (!this._waitingForCompletions || !completions || !completions.length) { | |
| this.hideSuggestBox(); | |
| return; | |
| } | |
| delete this._waitingForCompletions; | |
| var selectionRange = selection.getRangeAt(0); | |
| var fullWordRange = document.createRange(); | |
| fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset); | |
| fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset); | |
| if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString()) | |
| return; | |
| this._userEnteredRange = fullWordRange; | |
| this._userEnteredText = fullWordRange.toString(); | |
| if (this._suggestBox) | |
| this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), completions, !this.isCaretAtEndOfPrompt()); | |
| var wordPrefixLength = originalWordPrefixRange.toString().length; | |
| if (auto) { | |
| var completionText = completions[0]; | |
| var commonPrefix = this._buildCommonPrefix(completions, wordPrefixLength); | |
| this._commonPrefix = commonPrefix; | |
| } else { | |
| if (completions.length === 1) { | |
| var completionText = completions[0]; | |
| wordPrefixLength = completionText.length; | |
| } else { | |
| var commonPrefix = this._buildCommonPrefix(completions, wordPrefixLength); | |
| wordPrefixLength = commonPrefix.length; | |
| if (selection.isCollapsed) | |
| var completionText = completions[0]; | |
| else { | |
| var currentText = fullWordRange.toString(); | |
| var foundIndex = null; | |
| for (var i = 0; i < completions.length; ++i) { | |
| if (completions[i] === currentText) | |
| foundIndex = i; | |
| } | |
| var nextIndex = foundIndex + (reverse ? -1 : 1); | |
| if (foundIndex === null || nextIndex >= completions.length) | |
| var completionText = completions[0]; | |
| else if (nextIndex < 0) | |
| var completionText = completions[completions.length - 1]; | |
| else | |
| var completionText = completions[nextIndex]; | |
| } | |
| } | |
| } | |
| if (auto) { | |
| if (this.isCaretAtEndOfPrompt()) { | |
| this._userEnteredRange.deleteContents(); | |
| this._element.pruneEmptyTextNodes(); | |
| var finalSelectionRange = document.createRange(); | |
| var prefixText = completionText.substring(0, wordPrefixLength); | |
| var suffixText = completionText.substring(wordPrefixLength); | |
| var prefixTextNode = document.createTextNode(prefixText); | |
| fullWordRange.insertNode(prefixTextNode); | |
| this.autoCompleteElement = document.createElement("span"); | |
| this.autoCompleteElement.className = "auto-complete-text"; | |
| this.autoCompleteElement.textContent = suffixText; | |
| prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling); | |
| finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); | |
| finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); | |
| selection.removeAllRanges(); | |
| selection.addRange(finalSelectionRange); | |
| } | |
| } else | |
| this.applySuggestion(completionText, completions.length > 1, originalWordPrefixRange); | |
| }, | |
| _completeCommonPrefix: function() | |
| { | |
| if (!this.autoCompleteElement || !this._commonPrefix || !this._userEnteredText || !this._commonPrefix.startsWith(this._userEnteredText)) | |
| return; | |
| if (!this.isSuggestBoxVisible()) { | |
| this.acceptAutoComplete(); | |
| return; | |
| } | |
| this.autoCompleteElement.textContent = this._commonPrefix.substring(this._userEnteredText.length); | |
| this.acceptSuggestion(true) | |
| }, | |
| applySuggestion: function(completionText, isIntermediateSuggestion, originalPrefixRange) | |
| { | |
| var wordPrefixLength; | |
| if (originalPrefixRange) | |
| wordPrefixLength = originalPrefixRange.toString().length; | |
| else | |
| wordPrefixLength = this._userEnteredText ? this._userEnteredText.length : 0; | |
| this._userEnteredRange.deleteContents(); | |
| this._element.pruneEmptyTextNodes(); | |
| var finalSelectionRange = document.createRange(); | |
| var completionTextNode = document.createTextNode(completionText); | |
| this._userEnteredRange.insertNode(completionTextNode); | |
| if (this.autoCompleteElement && this.autoCompleteElement.parentNode) { | |
| this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement); | |
| delete this.autoCompleteElement; | |
| } | |
| if (isIntermediateSuggestion) | |
| finalSelectionRange.setStart(completionTextNode, wordPrefixLength); | |
| else | |
| finalSelectionRange.setStart(completionTextNode, completionText.length); | |
| finalSelectionRange.setEnd(completionTextNode, completionText.length); | |
| var selection = window.getSelection(); | |
| selection.removeAllRanges(); | |
| selection.addRange(finalSelectionRange); | |
| if (isIntermediateSuggestion) | |
| this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApplied, { itemText: completionText }); | |
| }, | |
| acceptSuggestion: function(prefixAccepted) | |
| { | |
| if (this._isAcceptingSuggestion) | |
| return false; | |
| if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode) | |
| return false; | |
| var text = this.autoCompleteElement.textContent; | |
| var textNode = document.createTextNode(text); | |
| this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement); | |
| delete this.autoCompleteElement; | |
| var finalSelectionRange = document.createRange(); | |
| finalSelectionRange.setStart(textNode, text.length); | |
| finalSelectionRange.setEnd(textNode, text.length); | |
| var selection = window.getSelection(); | |
| selection.removeAllRanges(); | |
| selection.addRange(finalSelectionRange); | |
| if (!prefixAccepted) { | |
| this.hideSuggestBox(); | |
| this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepted); | |
| } else | |
| this.autoCompleteSoon(true); | |
| return true; | |
| }, | |
| hideSuggestBox: function() | |
| { | |
| if (this.isSuggestBoxVisible()) | |
| this._suggestBox.hide(); | |
| }, | |
| isSuggestBoxVisible: function() | |
| { | |
| return this._suggestBox && this._suggestBox.visible; | |
| }, | |
| isCaretInsidePrompt: function() | |
| { | |
| return this._element.isInsertionCaretInside(); | |
| }, | |
| isCaretAtEndOfPrompt: function() | |
| { | |
| var selection = window.getSelection(); | |
| if (!selection.rangeCount || !selection.isCollapsed) | |
| return false; | |
| var selectionRange = selection.getRangeAt(0); | |
| var node = selectionRange.startContainer; | |
| if (!node.isSelfOrDescendant(this._element)) | |
| return false; | |
| if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length) | |
| return false; | |
| var foundNextText = false; | |
| while (node) { | |
| if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) { | |
| if (foundNextText && (!this.autoCompleteElement || !this.autoCompleteElement.isAncestor(node))) | |
| return false; | |
| foundNextText = true; | |
| } | |
| node = node.traverseNextNode(this._element); | |
| } | |
| return true; | |
| }, | |
| isCaretOnFirstLine: function() | |
| { | |
| var selection = window.getSelection(); | |
| var focusNode = selection.focusNode; | |
| if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this._element) | |
| return true; | |
| if (focusNode.textContent.substring(0, selection.focusOffset).indexOf("\n") !== -1) | |
| return false; | |
| focusNode = focusNode.previousSibling; | |
| while (focusNode) { | |
| if (focusNode.nodeType !== Node.TEXT_NODE) | |
| return true; | |
| if (focusNode.textContent.indexOf("\n") !== -1) | |
| return false; | |
| focusNode = focusNode.previousSibling; | |
| } | |
| return true; | |
| }, | |
| isCaretOnLastLine: function() | |
| { | |
| var selection = window.getSelection(); | |
| var focusNode = selection.focusNode; | |
| if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this._element) | |
| return true; | |
| if (focusNode.textContent.substring(selection.focusOffset).indexOf("\n") !== -1) | |
| return false; | |
| focusNode = focusNode.nextSibling; | |
| while (focusNode) { | |
| if (focusNode.nodeType !== Node.TEXT_NODE) | |
| return true; | |
| if (focusNode.textContent.indexOf("\n") !== -1) | |
| return false; | |
| focusNode = focusNode.nextSibling; | |
| } | |
| return true; | |
| }, | |
| moveCaretToEndOfPrompt: function() | |
| { | |
| var selection = window.getSelection(); | |
| var selectionRange = document.createRange(); | |
| var offset = this._element.childNodes.length; | |
| selectionRange.setStart(this._element, offset); | |
| selectionRange.setEnd(this._element, offset); | |
| selection.removeAllRanges(); | |
| selection.addRange(selectionRange); | |
| }, | |
| tabKeyPressed: function(event) | |
| { | |
| this._completeCommonPrefix(); | |
| return true; | |
| }, | |
| enterKeyPressed: function(event) | |
| { | |
| if (this.isSuggestBoxVisible()) | |
| return this._suggestBox.enterKeyPressed(event); | |
| return false; | |
| }, | |
| upKeyPressed: function(event) | |
| { | |
| if (this.isSuggestBoxVisible()) | |
| return this._suggestBox.upKeyPressed(event); | |
| return false; | |
| }, | |
| downKeyPressed: function(event) | |
| { | |
| if (this.isSuggestBoxVisible()) | |
| return this._suggestBox.downKeyPressed(event); | |
| return false; | |
| }, | |
| pageUpKeyPressed: function(event) | |
| { | |
| if (this.isSuggestBoxVisible()) | |
| return this._suggestBox.pageUpKeyPressed(event); | |
| return false; | |
| }, | |
| pageDownKeyPressed: function(event) | |
| { | |
| if (this.isSuggestBoxVisible()) | |
| return this._suggestBox.pageDownKeyPressed(event); | |
| return false; | |
| }, | |
| } | |
| WebInspector.TextPrompt.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.TextPromptWithHistory = function(completions, stopCharacters) | |
| { | |
| WebInspector.TextPrompt.call(this, completions, stopCharacters); | |
| this._data = []; | |
| this._historyOffset = 1; | |
| this._coalesceHistoryDupes = true; | |
| } | |
| WebInspector.TextPromptWithHistory.prototype = { | |
| get historyData() | |
| { | |
| return this._data; | |
| }, | |
| setCoalesceHistoryDupes: function(x) | |
| { | |
| this._coalesceHistoryDupes = x; | |
| }, | |
| setHistoryData: function(data) | |
| { | |
| this._data = [].concat(data); | |
| this._historyOffset = 1; | |
| }, | |
| pushHistoryItem: function(text) | |
| { | |
| if (this._uncommittedIsTop) { | |
| this._data.pop(); | |
| delete this._uncommittedIsTop; | |
| } | |
| this._historyOffset = 1; | |
| if (this._coalesceHistoryDupes && text === this._currentHistoryItem()) | |
| return; | |
| this._data.push(text); | |
| }, | |
| _pushCurrentText: function() | |
| { | |
| if (this._uncommittedIsTop) | |
| this._data.pop(); | |
| this._uncommittedIsTop = true; | |
| this.clearAutoComplete(true); | |
| this._data.push(this.text); | |
| }, | |
| _previous: function() | |
| { | |
| if (this._historyOffset > this._data.length) | |
| return undefined; | |
| if (this._historyOffset === 1) | |
| this._pushCurrentText(); | |
| ++this._historyOffset; | |
| return this._currentHistoryItem(); | |
| }, | |
| _next: function() | |
| { | |
| if (this._historyOffset === 1) | |
| return undefined; | |
| --this._historyOffset; | |
| return this._currentHistoryItem(); | |
| }, | |
| _currentHistoryItem: function() | |
| { | |
| return this._data[this._data.length - this._historyOffset]; | |
| }, | |
| defaultKeyHandler: function(event, force) | |
| { | |
| var newText; | |
| var isPrevious; | |
| switch (event.keyIdentifier) { | |
| case "Up": | |
| if (!this.isCaretOnFirstLine()) | |
| break; | |
| newText = this._previous(); | |
| isPrevious = true; | |
| break; | |
| case "Down": | |
| if (!this.isCaretOnLastLine()) | |
| break; | |
| newText = this._next(); | |
| break; | |
| case "U+0050": | |
| if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) { | |
| newText = this._previous(); | |
| isPrevious = true; | |
| } | |
| break; | |
| case "U+004E": | |
| if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) | |
| newText = this._next(); | |
| break; | |
| } | |
| if (newText !== undefined) { | |
| event.consume(true); | |
| this.text = newText; | |
| if (isPrevious) { | |
| var firstNewlineIndex = this.text.indexOf("\n"); | |
| if (firstNewlineIndex === -1) | |
| this.moveCaretToEndOfPrompt(); | |
| else { | |
| var selection = window.getSelection(); | |
| var selectionRange = document.createRange(); | |
| selectionRange.setStart(this._element.firstChild, firstNewlineIndex); | |
| selectionRange.setEnd(this._element.firstChild, firstNewlineIndex); | |
| selection.removeAllRanges(); | |
| selection.addRange(selectionRange); | |
| } | |
| } | |
| return true; | |
| } | |
| return WebInspector.TextPrompt.prototype.defaultKeyHandler.apply(this, arguments); | |
| } | |
| } | |
| WebInspector.TextPromptWithHistory.prototype.__proto__ = WebInspector.TextPrompt.prototype; | |
| WebInspector.TextPrompt.SuggestBox = function(textPrompt, inputElement, className) | |
| { | |
| this._textPrompt = textPrompt; | |
| this._inputElement = inputElement; | |
| this._selectedElement = null; | |
| this._boundOnScroll = this._onscrollresize.bind(this, true); | |
| this._boundOnResize = this._onscrollresize.bind(this, false); | |
| window.addEventListener("scroll", this._boundOnScroll, true); | |
| window.addEventListener("resize", this._boundOnResize, true); | |
| this._bodyElement = inputElement.ownerDocument.body; | |
| this._element = inputElement.ownerDocument.createElement("div"); | |
| this._element.className = "suggest-box " + (className || ""); | |
| this._element.addEventListener("mousedown", this._onboxmousedown.bind(this), true); | |
| this.containerElement = this._element.createChild("div", "container"); | |
| this.contentElement = this.containerElement.createChild("div", "content"); | |
| } | |
| WebInspector.TextPrompt.SuggestBox.prototype = { | |
| get visible() | |
| { | |
| return !!this._element.parentElement; | |
| }, | |
| get hasSelection() | |
| { | |
| return !!this._selectedElement; | |
| }, | |
| _onscrollresize: function(isScroll, event) | |
| { | |
| if (isScroll && this._element.isAncestor(event.target) || !this.visible) | |
| return; | |
| this._updateBoxPositionWithExistingAnchor(); | |
| }, | |
| _updateBoxPositionWithExistingAnchor: function() | |
| { | |
| this._updateBoxPosition(this._anchorBox); | |
| }, | |
| _updateBoxPosition: function(anchorBox) | |
| { | |
| this.contentElement.style.display = "inline-block"; | |
| document.body.appendChild(this.contentElement); | |
| this.contentElement.positionAt(0, 0); | |
| var contentWidth = this.contentElement.offsetWidth; | |
| var contentHeight = this.contentElement.offsetHeight; | |
| this.contentElement.style.display = "block"; | |
| this.containerElement.appendChild(this.contentElement); | |
| this._anchorBox = anchorBox; | |
| const spacer = 6; | |
| const suggestBoxPaddingX = 21; | |
| var maxWidth = document.body.offsetWidth - anchorBox.x - spacer; | |
| var width = Math.min(contentWidth, maxWidth - suggestBoxPaddingX) + suggestBoxPaddingX; | |
| var paddedWidth = contentWidth + suggestBoxPaddingX; | |
| var boxX = anchorBox.x; | |
| if (width < paddedWidth) { | |
| maxWidth = document.body.offsetWidth - spacer; | |
| width = Math.min(contentWidth, maxWidth - suggestBoxPaddingX) + suggestBoxPaddingX; | |
| boxX = document.body.offsetWidth - width; | |
| } | |
| const suggestBoxPaddingY = 2; | |
| var boxY; | |
| var aboveHeight = anchorBox.y; | |
| var underHeight = document.body.offsetHeight - anchorBox.y - anchorBox.height; | |
| var maxHeight = Math.max(underHeight, aboveHeight) - spacer; | |
| var height = Math.min(contentHeight, maxHeight - suggestBoxPaddingY) + suggestBoxPaddingY; | |
| if (underHeight >= aboveHeight) { | |
| boxY = anchorBox.y + anchorBox.height; | |
| this._element.removeStyleClass("above-anchor"); | |
| this._element.addStyleClass("under-anchor"); | |
| } else { | |
| boxY = anchorBox.y - height; | |
| this._element.removeStyleClass("under-anchor"); | |
| this._element.addStyleClass("above-anchor"); | |
| } | |
| this._element.positionAt(boxX, boxY); | |
| this._element.style.width = width + "px"; | |
| this._element.style.height = height + "px"; | |
| }, | |
| _onboxmousedown: function(event) | |
| { | |
| event.preventDefault(); | |
| }, | |
| hide: function() | |
| { | |
| if (!this.visible) | |
| return; | |
| this._element.parentElement.removeChild(this._element); | |
| delete this._selectedElement; | |
| }, | |
| removeFromElement: function() | |
| { | |
| window.removeEventListener("scroll", this._boundOnScroll, true); | |
| window.removeEventListener("resize", this._boundOnResize, true); | |
| this.hide(); | |
| }, | |
| _applySuggestion: function(text, isIntermediateSuggestion) | |
| { | |
| if (!this.visible || !(text || this._selectedElement)) | |
| return false; | |
| var suggestion = text || this._selectedElement.textContent; | |
| if (!suggestion) | |
| return false; | |
| this._textPrompt.applySuggestion(suggestion, isIntermediateSuggestion); | |
| return true; | |
| }, | |
| acceptSuggestion: function(text) | |
| { | |
| var result = this._applySuggestion(text, false); | |
| this.hide(); | |
| if (!result) | |
| return false; | |
| this._textPrompt.acceptSuggestion(); | |
| return true; | |
| }, | |
| _onNextItem: function(event, isPageScroll) | |
| { | |
| var children = this.contentElement.childNodes; | |
| if (!children.length) | |
| return false; | |
| if (!this._selectedElement) | |
| this._selectedElement = this.contentElement.firstChild; | |
| else { | |
| if (!isPageScroll) | |
| this._selectedElement = this._selectedElement.nextSibling || this.contentElement.firstChild; | |
| else { | |
| var candidate = this._selectedElement; | |
| for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) { | |
| if (candidate.nextSibling) | |
| candidate = candidate.nextSibling; | |
| else | |
| break; | |
| } | |
| this._selectedElement = candidate; | |
| } | |
| } | |
| this._updateSelection(); | |
| this._applySuggestion(undefined, true); | |
| return true; | |
| }, | |
| _onPreviousItem: function(event, isPageScroll) | |
| { | |
| var children = this.contentElement.childNodes; | |
| if (!children.length) | |
| return false; | |
| if (!this._selectedElement) | |
| this._selectedElement = this.contentElement.lastChild; | |
| else { | |
| if (!isPageScroll) | |
| this._selectedElement = this._selectedElement.previousSibling || this.contentElement.lastChild; | |
| else { | |
| var candidate = this._selectedElement; | |
| for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) { | |
| if (candidate.previousSibling) | |
| candidate = candidate.previousSibling; | |
| else | |
| break; | |
| } | |
| this._selectedElement = candidate; | |
| } | |
| } | |
| this._updateSelection(); | |
| this._applySuggestion(undefined, true); | |
| return true; | |
| }, | |
| updateSuggestions: function(anchorBox, completions, canShowForSingleItem) | |
| { | |
| if (this._suggestTimeout) { | |
| clearTimeout(this._suggestTimeout); | |
| delete this._suggestTimeout; | |
| } | |
| this._completionsReady(anchorBox, completions, canShowForSingleItem); | |
| }, | |
| _onItemMouseDown: function(text, event) | |
| { | |
| this.acceptSuggestion(text); | |
| event.consume(true); | |
| }, | |
| _createItemElement: function(prefix, text) | |
| { | |
| var element = document.createElement("div"); | |
| element.className = "suggest-box-content-item source-code"; | |
| element.tabIndex = -1; | |
| if (prefix && prefix.length && !text.indexOf(prefix)) { | |
| var prefixElement = element.createChild("span", "prefix"); | |
| prefixElement.textContent = prefix; | |
| var suffixElement = element.createChild("span", "suffix"); | |
| suffixElement.textContent = text.substring(prefix.length); | |
| } else { | |
| var suffixElement = element.createChild("span", "suffix"); | |
| suffixElement.textContent = text; | |
| } | |
| element.addEventListener("mousedown", this._onItemMouseDown.bind(this, text), false); | |
| return element; | |
| }, | |
| _updateItems: function(items, canShowForSingleItem) | |
| { | |
| this.contentElement.removeChildren(); | |
| var userEnteredText = this._textPrompt._userEnteredText; | |
| for (var i = 0; i < items.length; ++i) { | |
| var item = items[i]; | |
| var currentItemElement = this._createItemElement(userEnteredText, item); | |
| this.contentElement.appendChild(currentItemElement); | |
| } | |
| this._selectedElement = canShowForSingleItem ? this.contentElement.firstChild : null; | |
| this._updateSelection(); | |
| }, | |
| _updateSelection: function() | |
| { | |
| for (var child = this.contentElement.firstChild; child; child = child.nextSibling) { | |
| if (child !== this._selectedElement) | |
| child.removeStyleClass("selected"); | |
| } | |
| if (this._selectedElement) { | |
| this._selectedElement.addStyleClass("selected"); | |
| this._selectedElement.scrollIntoViewIfNeeded(false); | |
| } | |
| }, | |
| _canShowBox: function(completions, canShowForSingleItem) | |
| { | |
| if (!completions || !completions.length) | |
| return false; | |
| if (completions.length > 1) | |
| return true; | |
| return canShowForSingleItem && completions[0] !== this._textPrompt._userEnteredText; | |
| }, | |
| _rememberRowCountPerViewport: function() | |
| { | |
| if (!this.contentElement.firstChild) | |
| return; | |
| this._rowCountPerViewport = Math.floor(this.containerElement.offsetHeight / this.contentElement.firstChild.offsetHeight); | |
| }, | |
| _completionsReady: function(anchorBox, completions, canShowForSingleItem) | |
| { | |
| if (this._canShowBox(completions, canShowForSingleItem)) { | |
| this._updateItems(completions, canShowForSingleItem); | |
| this._updateBoxPosition(anchorBox); | |
| if (!this.visible) | |
| this._bodyElement.appendChild(this._element); | |
| this._rememberRowCountPerViewport(); | |
| } else | |
| this.hide(); | |
| }, | |
| upKeyPressed: function(event) | |
| { | |
| return this._onPreviousItem(event, false); | |
| }, | |
| downKeyPressed: function(event) | |
| { | |
| return this._onNextItem(event, false); | |
| }, | |
| pageUpKeyPressed: function(event) | |
| { | |
| return this._onPreviousItem(event, true); | |
| }, | |
| pageDownKeyPressed: function(event) | |
| { | |
| return this._onNextItem(event, true); | |
| }, | |
| enterKeyPressed: function(event) | |
| { | |
| var hasSelectedItem = !!this._selectedElement; | |
| this.acceptSuggestion(); | |
| return hasSelectedItem; | |
| }, | |
| tabKeyPressed: function(event) | |
| { | |
| return this.enterKeyPressed(event); | |
| } | |
| } | |
| WebInspector.Popover = function(popoverHelper) | |
| { | |
| this.element = document.createElement("div"); | |
| this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll"; | |
| this._popupArrowElement = document.createElement("div"); | |
| this._popupArrowElement.className = "arrow"; | |
| this.element.appendChild(this._popupArrowElement); | |
| this._contentDiv = document.createElement("div"); | |
| this._contentDiv.className = "content"; | |
| this._visible = false; | |
| this._popoverHelper = popoverHelper; | |
| } | |
| WebInspector.Popover.prototype = { | |
| show: function(contentElement, anchor, preferredWidth, preferredHeight) | |
| { | |
| if (this._disposed) | |
| return; | |
| this.contentElement = contentElement; | |
| if (WebInspector.Popover._popoverElement) | |
| document.body.removeChild(WebInspector.Popover._popoverElement); | |
| WebInspector.Popover._popoverElement = this.element; | |
| this.contentElement.positionAt(0, 0); | |
| document.body.appendChild(this.contentElement); | |
| preferredWidth = preferredWidth || this.contentElement.offsetWidth; | |
| preferredHeight = preferredHeight || this.contentElement.offsetHeight; | |
| this._contentDiv.appendChild(this.contentElement); | |
| this.element.appendChild(this._contentDiv); | |
| document.body.appendChild(this.element); | |
| this._positionElement(anchor, preferredWidth, preferredHeight); | |
| this._visible = true; | |
| if (this._popoverHelper) | |
| contentElement.addEventListener("mousemove", this._popoverHelper._killHidePopoverTimer.bind(this._popoverHelper), true); | |
| }, | |
| hide: function() | |
| { | |
| if (WebInspector.Popover._popoverElement) { | |
| delete WebInspector.Popover._popoverElement; | |
| document.body.removeChild(this.element); | |
| } | |
| this._visible = false; | |
| }, | |
| get visible() | |
| { | |
| return this._visible; | |
| }, | |
| get disposed() | |
| { | |
| return this._disposed; | |
| }, | |
| dispose: function() | |
| { | |
| if (this.visible) | |
| this.hide(); | |
| this._disposed = true; | |
| }, | |
| setCanShrink: function(canShrink) | |
| { | |
| this._hasFixedHeight = !canShrink; | |
| this._contentDiv.addStyleClass("fixed-height"); | |
| }, | |
| _positionElement: function(anchorElement, preferredWidth, preferredHeight) | |
| { | |
| const borderWidth = 25; | |
| const scrollerWidth = this._hasFixedHeight ? 0 : 11; | |
| const arrowHeight = 15; | |
| const arrowOffset = 10; | |
| const borderRadius = 10; | |
| preferredWidth = Math.max(preferredWidth, 50); | |
| const totalWidth = window.innerWidth; | |
| const totalHeight = window.innerHeight; | |
| var anchorBox = anchorElement.boxInWindow(window); | |
| var newElementPosition = { x: 0, y: 0, width: preferredWidth + scrollerWidth, height: preferredHeight }; | |
| var verticalAlignment; | |
| var roomAbove = anchorBox.y; | |
| var roomBelow = totalHeight - anchorBox.y - anchorBox.height; | |
| if (roomAbove > roomBelow) { | |
| if (anchorBox.y > newElementPosition.height + arrowHeight + borderRadius) | |
| newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHeight; | |
| else { | |
| newElementPosition.y = borderRadius; | |
| newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight; | |
| if (this._hasFixedHeight && newElementPosition.height < preferredHeight) { | |
| newElementPosition.y = borderRadius; | |
| newElementPosition.height = preferredHeight; | |
| } | |
| } | |
| verticalAlignment = "bottom"; | |
| } else { | |
| newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight; | |
| if (newElementPosition.y + newElementPosition.height + arrowHeight - borderWidth >= totalHeight) { | |
| newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height - borderRadius * 2 - arrowHeight; | |
| if (this._hasFixedHeight && newElementPosition.height < preferredHeight) { | |
| newElementPosition.y = totalHeight - preferredHeight - borderRadius; | |
| newElementPosition.height = preferredHeight; | |
| } | |
| } | |
| verticalAlignment = "top"; | |
| } | |
| var horizontalAlignment; | |
| if (anchorBox.x + newElementPosition.width < totalWidth) { | |
| newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRadius - arrowOffset); | |
| horizontalAlignment = "left"; | |
| } else if (newElementPosition.width + borderRadius * 2 < totalWidth) { | |
| newElementPosition.x = totalWidth - newElementPosition.width - borderRadius; | |
| horizontalAlignment = "right"; | |
| var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anchorBox.width - borderRadius - arrowOffset); | |
| arrowRightPosition += anchorBox.width / 2; | |
| arrowRightPosition = Math.min(arrowRightPosition, newElementPosition.width - borderRadius - arrowOffset); | |
| this._popupArrowElement.style.right = arrowRightPosition + "px"; | |
| } else { | |
| newElementPosition.x = borderRadius; | |
| newElementPosition.width = totalWidth - borderRadius * 2; | |
| newElementPosition.height += scrollerWidth; | |
| horizontalAlignment = "left"; | |
| if (verticalAlignment === "bottom") | |
| newElementPosition.y -= scrollerWidth; | |
| this._popupArrowElement.style.left = Math.max(0, anchorBox.x - borderRadius * 2 - arrowOffset) + "px"; | |
| this._popupArrowElement.style.left += anchorBox.width / 2; | |
| } | |
| this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll " + verticalAlignment + "-" + horizontalAlignment + "-arrow"; | |
| this.element.positionAt(newElementPosition.x - borderWidth, newElementPosition.y - borderWidth); | |
| this.element.style.width = newElementPosition.width + borderWidth * 2 + "px"; | |
| this.element.style.height = newElementPosition.height + borderWidth * 2 + "px"; | |
| } | |
| } | |
| WebInspector.PopoverHelper = function(panelElement, getAnchor, showPopover, onHide, disableOnClick) | |
| { | |
| this._panelElement = panelElement; | |
| this._getAnchor = getAnchor; | |
| this._showPopover = showPopover; | |
| this._onHide = onHide; | |
| this._disableOnClick = !!disableOnClick; | |
| panelElement.addEventListener("mousedown", this._mouseDown.bind(this), false); | |
| panelElement.addEventListener("mousemove", this._mouseMove.bind(this), false); | |
| panelElement.addEventListener("mouseout", this._mouseOut.bind(this), false); | |
| this.setTimeout(1000); | |
| } | |
| WebInspector.PopoverHelper.prototype = { | |
| setTimeout: function(timeout) | |
| { | |
| this._timeout = timeout; | |
| }, | |
| _mouseDown: function(event) | |
| { | |
| if (this._disableOnClick || !event.target.isSelfOrDescendant(this._hoverElement)) | |
| this.hidePopover(); | |
| else { | |
| this._killHidePopoverTimer(); | |
| this._handleMouseAction(event, true); | |
| } | |
| }, | |
| _mouseMove: function(event) | |
| { | |
| if (event.target.isSelfOrDescendant(this._hoverElement)) | |
| return; | |
| this._startHidePopoverTimer(); | |
| this._handleMouseAction(event, false); | |
| }, | |
| _mouseOut: function(event) | |
| { | |
| if (event.target === this._hoverElement) | |
| this._startHidePopoverTimer(); | |
| }, | |
| _startHidePopoverTimer: function() | |
| { | |
| if (!this._popover || this._hidePopoverTimer) | |
| return; | |
| function doHide() | |
| { | |
| this._hidePopover(); | |
| delete this._hidePopoverTimer; | |
| } | |
| this._hidePopoverTimer = setTimeout(doHide.bind(this), this._timeout / 2); | |
| }, | |
| _handleMouseAction: function(event, isMouseDown) | |
| { | |
| this._resetHoverTimer(); | |
| if (event.which && this._disableOnClick) | |
| return; | |
| this._hoverElement = this._getAnchor(event.target, event); | |
| if (!this._hoverElement) | |
| return; | |
| const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout); | |
| this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay); | |
| }, | |
| _resetHoverTimer: function() | |
| { | |
| if (this._hoverTimer) { | |
| clearTimeout(this._hoverTimer); | |
| delete this._hoverTimer; | |
| } | |
| }, | |
| isPopoverVisible: function() | |
| { | |
| return !!this._popover; | |
| }, | |
| hidePopover: function() | |
| { | |
| this._resetHoverTimer(); | |
| this._hidePopover(); | |
| }, | |
| _hidePopover: function() | |
| { | |
| if (!this._popover) | |
| return; | |
| if (this._onHide) | |
| this._onHide(); | |
| this._popover.dispose(); | |
| delete this._popover; | |
| this._hoverElement = null; | |
| }, | |
| _mouseHover: function(element) | |
| { | |
| delete this._hoverTimer; | |
| this._hidePopover(); | |
| this._popover = new WebInspector.Popover(this); | |
| this._showPopover(element, this._popover); | |
| }, | |
| _killHidePopoverTimer: function() | |
| { | |
| if (this._hidePopoverTimer) { | |
| clearTimeout(this._hidePopoverTimer); | |
| delete this._hidePopoverTimer; | |
| this._resetHoverTimer(); | |
| } | |
| } | |
| } | |
| WebInspector.Placard = function(title, subtitle) | |
| { | |
| this.element = document.createElement("div"); | |
| this.element.className = "placard"; | |
| this.element.placard = this; | |
| this.titleElement = document.createElement("div"); | |
| this.titleElement.className = "title"; | |
| this.subtitleElement = document.createElement("div"); | |
| this.subtitleElement.className = "subtitle"; | |
| this.element.appendChild(this.subtitleElement); | |
| this.element.appendChild(this.titleElement); | |
| this.title = title; | |
| this.subtitle = subtitle; | |
| this.selected = false; | |
| } | |
| WebInspector.Placard.prototype = { | |
| get title() | |
| { | |
| return this._title; | |
| }, | |
| set title(x) | |
| { | |
| if (this._title === x) | |
| return; | |
| this._title = x; | |
| this.titleElement.textContent = x; | |
| }, | |
| get subtitle() | |
| { | |
| return this._subtitle; | |
| }, | |
| set subtitle(x) | |
| { | |
| if (this._subtitle === x) | |
| return; | |
| this._subtitle = x; | |
| this.subtitleElement.textContent = x; | |
| }, | |
| get selected() | |
| { | |
| return this._selected; | |
| }, | |
| set selected(x) | |
| { | |
| if (x) | |
| this.select(); | |
| else | |
| this.deselect(); | |
| }, | |
| select: function() | |
| { | |
| if (this._selected) | |
| return; | |
| this._selected = true; | |
| this.element.addStyleClass("selected"); | |
| }, | |
| deselect: function() | |
| { | |
| if (!this._selected) | |
| return; | |
| this._selected = false; | |
| this.element.removeStyleClass("selected"); | |
| }, | |
| toggleSelected: function() | |
| { | |
| this.selected = !this.selected; | |
| }, | |
| discard: function() | |
| { | |
| } | |
| } | |
| WebInspector.TabbedPane = function() | |
| { | |
| WebInspector.View.call(this); | |
| this.registerRequiredCSS("tabbedPane.css"); | |
| this.element.addStyleClass("tabbed-pane"); | |
| this._headerElement = this.element.createChild("div", "tabbed-pane-header"); | |
| this._headerContentsElement = this._headerElement.createChild("div", "tabbed-pane-header-contents"); | |
| this._tabsElement = this._headerContentsElement.createChild("div", "tabbed-pane-header-tabs"); | |
| this._contentElement = this.element.createChild("div", "tabbed-pane-content"); | |
| this._tabs = []; | |
| this._tabsHistory = []; | |
| this._tabsById = {}; | |
| this.element.addEventListener("click", this.focus.bind(this), false); | |
| this._dropDownButton = this._createDropDownButton(); | |
| } | |
| WebInspector.TabbedPane.EventTypes = { | |
| TabSelected: "TabSelected", | |
| TabClosed: "TabClosed" | |
| } | |
| WebInspector.TabbedPane.prototype = { | |
| get visibleView() | |
| { | |
| return this._currentTab ? this._currentTab.view : null; | |
| }, | |
| get selectedTabId() | |
| { | |
| return this._currentTab ? this._currentTab.id : null; | |
| }, | |
| set shrinkableTabs(shrinkableTabs) | |
| { | |
| this._shrinkableTabs = shrinkableTabs; | |
| }, | |
| set closeableTabs(closeableTabs) | |
| { | |
| this._closeableTabs = closeableTabs; | |
| }, | |
| defaultFocusedElement: function() | |
| { | |
| return this.visibleView ? this.visibleView.defaultFocusedElement() : null; | |
| }, | |
| appendTab: function(id, tabTitle, view, tabTooltip, userGesture) | |
| { | |
| var tab = new WebInspector.TabbedPaneTab(this, id, tabTitle, this._closeableTabs, view, tabTooltip); | |
| this._tabsById[id] = tab; | |
| this._tabs.push(tab); | |
| this._tabsHistory.push(tab); | |
| if (this._tabsHistory[0] === tab) | |
| this.selectTab(tab.id, userGesture); | |
| this._updateTabElements(); | |
| }, | |
| closeTab: function(id, userGesture) | |
| { | |
| this._innerCloseTab(id, userGesture); | |
| this._updateTabElements(); | |
| if (this._tabsHistory.length) | |
| this.selectTab(this._tabsHistory[0].id, userGesture); | |
| }, | |
| _innerCloseTab: function(id, userGesture) | |
| { | |
| if (this._currentTab && this._currentTab.id === id) | |
| this._hideCurrentTab(); | |
| var tab = this._tabsById[id]; | |
| delete this._tabsById[id]; | |
| this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1); | |
| this._tabs.splice(this._tabs.indexOf(tab), 1); | |
| if (tab._shown) | |
| this._hideTabElement(tab); | |
| var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture }; | |
| this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabClosed, eventData); | |
| return true; | |
| }, | |
| closeAllTabs: function(userGesture) | |
| { | |
| var tabs = this._tabs.slice(); | |
| for (var i = 0; i < tabs.length; ++i) | |
| this._innerCloseTab(tabs[i].id, userGesture); | |
| this._updateTabElements(); | |
| }, | |
| closeOtherTabs: function(id) | |
| { | |
| var tabs = this._tabs.slice(); | |
| for (var i = 0; i < tabs.length; ++i) { | |
| if (tabs[i].id !== id) | |
| this._innerCloseTab(tabs[i].id, true); | |
| } | |
| this._updateTabElements(); | |
| this.selectTab(id, true); | |
| }, | |
| selectTab: function(id, userGesture) | |
| { | |
| var tab = this._tabsById[id]; | |
| if (!tab) | |
| return; | |
| if (this._currentTab && this._currentTab.id === id) | |
| return; | |
| this._hideCurrentTab(); | |
| this._showTab(tab); | |
| this._currentTab = tab; | |
| this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1); | |
| this._tabsHistory.splice(0, 0, tab); | |
| this._updateTabElements(); | |
| var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture }; | |
| this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabSelected, eventData); | |
| return true; | |
| }, | |
| lastOpenedTabIds: function(tabsCount) | |
| { | |
| function tabToTabId(tab) { | |
| return tab.id; | |
| } | |
| return this._tabsHistory.slice(0, tabsCount).map(tabToTabId); | |
| }, | |
| changeTabTitle: function(id, tabTitle) | |
| { | |
| var tab = this._tabsById[id]; | |
| tab.title = tabTitle; | |
| this._updateTabElements(); | |
| }, | |
| changeTabView: function(id, view) | |
| { | |
| var tab = this._tabsById[id]; | |
| if (this._currentTab && this._currentTab.id === tab.id) { | |
| this._hideTab(tab); | |
| tab.view = view; | |
| this._showTab(tab); | |
| } else | |
| tab.view = view; | |
| }, | |
| changeTabTooltip: function(id, tabTooltip) | |
| { | |
| var tab = this._tabsById[id]; | |
| tab.tooltip = tabTooltip; | |
| }, | |
| onResize: function() | |
| { | |
| this._updateTabElements(); | |
| }, | |
| _updateTabElements: function() | |
| { | |
| WebInspector.invokeOnceAfterBatchUpdate(this, this._innerUpdateTabElements); | |
| }, | |
| _innerUpdateTabElements: function() | |
| { | |
| if (!this.isShowing()) | |
| return; | |
| if (!this._tabs.length) | |
| this._contentElement.addStyleClass("has-no-tabs"); | |
| else | |
| this._contentElement.removeStyleClass("has-no-tabs"); | |
| if (!this._measuredDropDownButtonWidth) | |
| this._measureDropDownButton(); | |
| this._updateWidths(); | |
| this._updateTabsDropDown(); | |
| }, | |
| _showTabElement: function(index, tab) | |
| { | |
| if (index >= this._tabsElement.children.length) | |
| this._tabsElement.appendChild(tab.tabElement); | |
| else | |
| this._tabsElement.insertBefore(tab.tabElement, this._tabsElement.children[index]); | |
| tab._shown = true; | |
| }, | |
| _hideTabElement: function(tab) | |
| { | |
| this._tabsElement.removeChild(tab.tabElement); | |
| tab._shown = false; | |
| }, | |
| _createDropDownButton: function() | |
| { | |
| var dropDownContainer = document.createElement("div"); | |
| dropDownContainer.addStyleClass("tabbed-pane-header-tabs-drop-down-container"); | |
| var dropDownButton = dropDownContainer.createChild("div", "tabbed-pane-header-tabs-drop-down"); | |
| dropDownButton.appendChild(document.createTextNode("\u00bb")); | |
| this._tabsSelect = dropDownButton.createChild("select", "tabbed-pane-header-tabs-drop-down-select"); | |
| this._tabsSelect.addEventListener("change", this._tabsSelectChanged.bind(this), false); | |
| return dropDownContainer; | |
| }, | |
| _totalWidth: function() | |
| { | |
| return this._headerContentsElement.getBoundingClientRect().width; | |
| }, | |
| _updateTabsDropDown: function() | |
| { | |
| var tabsToShowIndexes = this._tabsToShowIndexes(this._tabs, this._tabsHistory, this._totalWidth(), this._measuredDropDownButtonWidth); | |
| for (var i = 0; i < this._tabs.length; ++i) { | |
| if (this._tabs[i]._shown && tabsToShowIndexes.indexOf(i) === -1) | |
| this._hideTabElement(this._tabs[i]); | |
| } | |
| for (var i = 0; i < tabsToShowIndexes.length; ++i) { | |
| var tab = this._tabs[tabsToShowIndexes[i]]; | |
| if (!tab._shown) | |
| this._showTabElement(i, tab); | |
| } | |
| this._populateDropDownFromIndex(); | |
| }, | |
| _populateDropDownFromIndex: function() | |
| { | |
| if (this._dropDownButton.parentElement) | |
| this._headerContentsElement.removeChild(this._dropDownButton); | |
| this._tabsSelect.removeChildren(); | |
| var tabsToShow = []; | |
| for (var i = 0; i < this._tabs.length; ++i) { | |
| if (!this._tabs[i]._shown) | |
| tabsToShow.push(this._tabs[i]); | |
| continue; | |
| } | |
| function compareFunction(tab1, tab2) | |
| { | |
| return tab1.title.localeCompare(tab2.title); | |
| } | |
| tabsToShow.sort(compareFunction); | |
| for (var i = 0; i < tabsToShow.length; ++i) { | |
| var option = new Option(tabsToShow[i].title); | |
| option.tab = tabsToShow[i]; | |
| this._tabsSelect.appendChild(option); | |
| } | |
| if (this._tabsSelect.options.length) { | |
| this._headerContentsElement.appendChild(this._dropDownButton); | |
| this._tabsSelect.selectedIndex = -1; | |
| } | |
| }, | |
| _tabsSelectChanged: function() | |
| { | |
| var options = this._tabsSelect.options; | |
| var selectedOption = options[this._tabsSelect.selectedIndex]; | |
| this.selectTab(selectedOption.tab.id, true); | |
| }, | |
| _measureDropDownButton: function() | |
| { | |
| this._dropDownButton.addStyleClass("measuring"); | |
| this._headerContentsElement.appendChild(this._dropDownButton); | |
| this._measuredDropDownButtonWidth = this._dropDownButton.getBoundingClientRect().width; | |
| this._headerContentsElement.removeChild(this._dropDownButton); | |
| this._dropDownButton.removeStyleClass("measuring"); | |
| }, | |
| _updateWidths: function() | |
| { | |
| var measuredWidths = this._measureWidths(); | |
| var maxWidth = this._shrinkableTabs ? this._calculateMaxWidth(measuredWidths.slice(), this._totalWidth()) : Number.MAX_VALUE; | |
| var i = 0; | |
| for (var tabId in this._tabs) { | |
| var tab = this._tabs[tabId]; | |
| tab.setWidth(Math.min(maxWidth, measuredWidths[i++])); | |
| } | |
| }, | |
| _measureWidths: function() | |
| { | |
| var measuringTabElements = []; | |
| for (var tabId in this._tabs) { | |
| var tab = this._tabs[tabId]; | |
| if (typeof tab._measuredWidth === "number") | |
| continue; | |
| var measuringTabElement = tab._createTabElement(true); | |
| measuringTabElement.__tab = tab; | |
| measuringTabElements.push(measuringTabElement); | |
| this._tabsElement.appendChild(measuringTabElement); | |
| } | |
| for (var i = 0; i < measuringTabElements.length; ++i) | |
| measuringTabElements[i].__tab._measuredWidth = measuringTabElements[i].getBoundingClientRect().width; | |
| for (var i = 0; i < measuringTabElements.length; ++i) | |
| measuringTabElements[i].parentElement.removeChild(measuringTabElements[i]); | |
| var measuredWidths = []; | |
| for (var tabId in this._tabs) | |
| measuredWidths.push(this._tabs[tabId]._measuredWidth); | |
| return measuredWidths; | |
| }, | |
| _calculateMaxWidth: function(measuredWidths, totalWidth) | |
| { | |
| if (!measuredWidths.length) | |
| return 0; | |
| measuredWidths.sort(function(x, y) { return x - y }); | |
| var totalMeasuredWidth = 0; | |
| for (var i = 0; i < measuredWidths.length; ++i) | |
| totalMeasuredWidth += measuredWidths[i]; | |
| if (totalWidth >= totalMeasuredWidth) | |
| return measuredWidths[measuredWidths.length - 1]; | |
| var totalExtraWidth = 0; | |
| for (var i = measuredWidths.length - 1; i > 0; --i) { | |
| var extraWidth = measuredWidths[i] - measuredWidths[i - 1]; | |
| totalExtraWidth += (measuredWidths.length - i) * extraWidth; | |
| if (totalWidth + totalExtraWidth >= totalMeasuredWidth) | |
| return measuredWidths[i - 1] + (totalWidth + totalExtraWidth - totalMeasuredWidth) / (measuredWidths.length - i); | |
| } | |
| return totalWidth / measuredWidths.length; | |
| }, | |
| _tabsToShowIndexes: function(tabsOrdered, tabsHistory, totalWidth, measuredDropDownButtonWidth) | |
| { | |
| var tabsToShowIndexes = []; | |
| var totalTabsWidth = 0; | |
| for (var i = 0; i < tabsHistory.length; ++i) { | |
| totalTabsWidth += tabsHistory[i].width(); | |
| var minimalRequiredWidth = totalTabsWidth; | |
| if (i !== tabsHistory.length - 1) | |
| minimalRequiredWidth += measuredDropDownButtonWidth; | |
| if (minimalRequiredWidth > totalWidth) | |
| break; | |
| tabsToShowIndexes.push(tabsOrdered.indexOf(tabsHistory[i])); | |
| } | |
| tabsToShowIndexes.sort(function(x, y) { return x - y }); | |
| return tabsToShowIndexes; | |
| }, | |
| _hideCurrentTab: function() | |
| { | |
| if (!this._currentTab) | |
| return; | |
| this._hideTab(this._currentTab); | |
| delete this._currentTab; | |
| }, | |
| _showTab: function(tab) | |
| { | |
| tab.tabElement.addStyleClass("selected"); | |
| tab.view.show(this._contentElement); | |
| }, | |
| _hideTab: function(tab) | |
| { | |
| tab.tabElement.removeStyleClass("selected"); | |
| tab.view.detach(); | |
| }, | |
| canHighlightLine: function() | |
| { | |
| return this._currentTab && this._currentTab.view && this._currentTab.view.canHighlightLine(); | |
| }, | |
| highlightLine: function(line) | |
| { | |
| if (this.canHighlightLine()) | |
| this._currentTab.view.highlightLine(line); | |
| }, | |
| elementsToRestoreScrollPositionsFor: function() | |
| { | |
| return [ this._contentElement ]; | |
| }, | |
| _insertBefore: function(tab, index) | |
| { | |
| this._tabsElement.insertBefore(tab._tabElement, this._tabsElement.childNodes[index]); | |
| var oldIndex = this._tabs.indexOf(tab); | |
| this._tabs.splice(oldIndex, 1); | |
| if (oldIndex < index) | |
| --index; | |
| this._tabs.splice(index, 0, tab); | |
| } | |
| } | |
| WebInspector.TabbedPane.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.TabbedPaneTab = function(tabbedPane, id, title, closeable, view, tooltip) | |
| { | |
| this._closeable = closeable; | |
| this._tabbedPane = tabbedPane; | |
| this._id = id; | |
| this._title = title; | |
| this._tooltip = tooltip; | |
| this._view = view; | |
| this._shown = false; | |
| this._measuredWidth; | |
| this._tabElement; | |
| } | |
| WebInspector.TabbedPaneTab.prototype = { | |
| get id() | |
| { | |
| return this._id; | |
| }, | |
| get title() | |
| { | |
| return this._title; | |
| }, | |
| set title(title) | |
| { | |
| this._title = title; | |
| if (this._titleElement) | |
| this._titleElement.textContent = title; | |
| delete this._measuredWidth; | |
| }, | |
| get view() | |
| { | |
| return this._view; | |
| }, | |
| set view(view) | |
| { | |
| this._view = view; | |
| }, | |
| get tooltip() | |
| { | |
| return this._tooltip; | |
| }, | |
| set tooltip(tooltip) | |
| { | |
| this._tooltip = tooltip; | |
| if (this._titleElement) | |
| this._titleElement.title = tooltip || ""; | |
| }, | |
| get tabElement() | |
| { | |
| if (typeof(this._tabElement) !== "undefined") | |
| return this._tabElement; | |
| this._createTabElement(false); | |
| return this._tabElement; | |
| }, | |
| width: function() | |
| { | |
| return this._width; | |
| }, | |
| setWidth: function(width) | |
| { | |
| this.tabElement.style.width = width + "px"; | |
| this._width = width; | |
| }, | |
| _createTabElement: function(measuring) | |
| { | |
| var tabElement = document.createElement("div"); | |
| tabElement.addStyleClass("tabbed-pane-header-tab"); | |
| tabElement.tabIndex = -1; | |
| var titleElement = tabElement.createChild("span", "tabbed-pane-header-tab-title"); | |
| titleElement.textContent = this.title; | |
| titleElement.title = this.tooltip || ""; | |
| if (!measuring) | |
| this._titleElement = titleElement; | |
| if (this._closeable) { | |
| var closeButtonSpan = tabElement.createChild("span", "tabbed-pane-header-tab-close-button"); | |
| closeButtonSpan.textContent = "\u00D7"; | |
| } | |
| if (measuring) | |
| tabElement.addStyleClass("measuring"); | |
| else { | |
| this._tabElement = tabElement; | |
| tabElement.addEventListener("click", this._tabClicked.bind(this), false); | |
| tabElement.addEventListener("mousedown", this._tabMouseDown.bind(this), false); | |
| if (this._closeable) { | |
| tabElement.addEventListener("contextmenu", this._tabContextMenu.bind(this), false); | |
| WebInspector.installDragHandle(tabElement, this._startTabDragging.bind(this), this._tabDragging.bind(this), this._endTabDragging.bind(this), "pointer"); | |
| } | |
| } | |
| return tabElement; | |
| }, | |
| _tabClicked: function(event) | |
| { | |
| if (this._closeable && (event.button === 1 || event.target.hasStyleClass("tabbed-pane-header-tab-close-button"))) | |
| this._tabbedPane.closeTab(this.id, true); | |
| }, | |
| _tabMouseDown: function(event) | |
| { | |
| if (event.target.hasStyleClass("tabbed-pane-header-tab-close-button") || event.button === 1) | |
| return; | |
| this._tabbedPane.selectTab(this.id, true); | |
| }, | |
| _tabContextMenu: function(event) | |
| { | |
| function close() | |
| { | |
| this._tabbedPane.closeTab(this.id, true); | |
| } | |
| function closeOthers() | |
| { | |
| this._tabbedPane.closeOtherTabs(this.id); | |
| } | |
| function closeAll() | |
| { | |
| this._tabbedPane.closeAllTabs(true); | |
| } | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| contextMenu.appendItem(WebInspector.UIString("Close"), close.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString("Close Others"), closeOthers.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString("Close All"), closeAll.bind(this)); | |
| contextMenu.show(event); | |
| }, | |
| _startTabDragging: function(event) | |
| { | |
| if (event.target.hasStyleClass("tabbed-pane-header-tab-close-button")) | |
| return false; | |
| this._dragStartX = event.pageX; | |
| return true; | |
| }, | |
| _tabDragging: function(event) | |
| { | |
| var tabElements = this._tabbedPane._tabsElement.childNodes; | |
| for (var i = 0; i < tabElements.length; ++i) { | |
| var tabElement = tabElements[i]; | |
| if (tabElement === this._tabElement) | |
| continue; | |
| var intersects = tabElement.offsetLeft + tabElement.clientWidth > this._tabElement.offsetLeft && | |
| this._tabElement.offsetLeft + this._tabElement.clientWidth > tabElement.offsetLeft; | |
| if (!intersects) | |
| continue; | |
| if (Math.abs(event.pageX - this._dragStartX) < tabElement.clientWidth / 2 + 5) | |
| break; | |
| if (event.pageX - this._dragStartX > 0) { | |
| tabElement = tabElement.nextSibling; | |
| ++i; | |
| } | |
| var oldOffsetLeft = this._tabElement.offsetLeft; | |
| this._tabbedPane._insertBefore(this, i); | |
| this._dragStartX += this._tabElement.offsetLeft - oldOffsetLeft; | |
| break; | |
| } | |
| if (!this._tabElement.previousSibling && event.pageX - this._dragStartX < 0) { | |
| this._tabElement.style.setProperty("left", "0px"); | |
| return; | |
| } | |
| if (!this._tabElement.nextSibling && event.pageX - this._dragStartX > 0) { | |
| this._tabElement.style.setProperty("left", "0px"); | |
| return; | |
| } | |
| this._tabElement.style.setProperty("position", "relative"); | |
| this._tabElement.style.setProperty("left", (event.pageX - this._dragStartX) + "px"); | |
| }, | |
| _endTabDragging: function(event) | |
| { | |
| this._tabElement.style.removeProperty("position"); | |
| this._tabElement.style.removeProperty("left"); | |
| delete this._dragStartX; | |
| } | |
| } | |
| WebInspector.Drawer = function() | |
| { | |
| this.element = document.getElementById("drawer"); | |
| this._savedHeight = 200; | |
| this._mainElement = document.getElementById("main"); | |
| this._toolbarElement = document.getElementById("toolbar"); | |
| this._floatingStatusBarContainer = document.getElementById("floating-status-bar-container"); | |
| WebInspector.installDragHandle(this._floatingStatusBarContainer, this._startStatusBarDragging.bind(this), this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), "row-resize"); | |
| this._drawerContentsElement = document.createElement("div"); | |
| this._drawerContentsElement.id = "drawer-contents"; | |
| this._drawerContentsElement.className = "drawer-contents"; | |
| this.element.appendChild(this._drawerContentsElement); | |
| this._viewStatusBar = document.createElement("div"); | |
| this._bottomStatusBar = document.getElementById("bottom-status-bar-container"); | |
| } | |
| WebInspector.Drawer.AnimationType = { | |
| Immediately: 0, | |
| Normal: 1, | |
| Slow: 2 | |
| } | |
| WebInspector.Drawer.prototype = { | |
| get visible() | |
| { | |
| return !!this._view; | |
| }, | |
| _constrainHeight: function(height) | |
| { | |
| return Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop() - Preferences.minConsoleHeight); | |
| }, | |
| show: function(view, animationType) | |
| { | |
| this.immediatelyFinishAnimation(); | |
| var drawerWasVisible = this.visible; | |
| if (this._view) { | |
| this._view.detach(); | |
| this._drawerContentsElement.removeChildren(); | |
| } | |
| this._view = view; | |
| var statusBarItems = this._view.statusBarItems || []; | |
| this._viewStatusBar.removeChildren(); | |
| for (var i = 0; i < statusBarItems.length; ++i) | |
| this._viewStatusBar.appendChild(statusBarItems[i]); | |
| document.body.addStyleClass("drawer-visible"); | |
| this._floatingStatusBarContainer.insertBefore(document.getElementById("panel-status-bar"), this._floatingStatusBarContainer.firstElementChild); | |
| this._bottomStatusBar.appendChild(this._viewStatusBar); | |
| this._view.markAsRoot(); | |
| this._view.show(this._drawerContentsElement); | |
| if (drawerWasVisible) | |
| return; | |
| var height = this._constrainHeight(this._savedHeight || this.element.offsetHeight); | |
| var animations = [ | |
| {element: this.element, end: {height: height}}, | |
| {element: this._mainElement, end: {bottom: height}}, | |
| {element: this._floatingStatusBarContainer, start: {"padding-left": this._bottomStatusBar.offsetLeft}, end: {"padding-left": 0}}, | |
| {element: this._viewStatusBar, start: {opacity: 0}, end: {opacity: 1}} | |
| ]; | |
| function animationFinished() | |
| { | |
| WebInspector.inspectorView.currentPanel().doResize(); | |
| if (this._view && this._view.afterShow) | |
| this._view.afterShow(); | |
| delete this._currentAnimation; | |
| } | |
| this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(animationType), animationFinished.bind(this)); | |
| if (animationType === WebInspector.Drawer.AnimationType.Immediately) | |
| this._currentAnimation.forceComplete(); | |
| }, | |
| hide: function(animationType) | |
| { | |
| this.immediatelyFinishAnimation(); | |
| if (!this.visible) | |
| return; | |
| this._savedHeight = this.element.offsetHeight; | |
| WebInspector.restoreFocusFromElement(this.element); | |
| document.body.removeStyleClass("drawer-visible"); | |
| WebInspector.inspectorView.currentPanel().statusBarResized(); | |
| document.body.addStyleClass("drawer-visible"); | |
| var animations = [ | |
| {element: this._mainElement, end: {bottom: 0}}, | |
| {element: this.element, end: {height: 0}}, | |
| {element: this._floatingStatusBarContainer, start: {"padding-left": 0}, end: {"padding-left": this._bottomStatusBar.offsetLeft} }, | |
| {element: this._viewStatusBar, start: {opacity: 1}, end: {opacity: 0}} | |
| ]; | |
| function animationFinished() | |
| { | |
| WebInspector.inspectorView.currentPanel().doResize(); | |
| this._view.detach(); | |
| delete this._view; | |
| this._bottomStatusBar.removeChildren(); | |
| this._bottomStatusBar.appendChild(document.getElementById("panel-status-bar")); | |
| this._drawerContentsElement.removeChildren(); | |
| document.body.removeStyleClass("drawer-visible"); | |
| delete this._currentAnimation; | |
| } | |
| this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(animationType), animationFinished.bind(this)); | |
| if (animationType === WebInspector.Drawer.AnimationType.Immediately) | |
| this._currentAnimation.forceComplete(); | |
| }, | |
| resize: function() | |
| { | |
| if (!this.visible) | |
| return; | |
| this._view.storeScrollPositions(); | |
| var height = this._constrainHeight(parseInt(this.element.style.height, 10)); | |
| this._mainElement.style.bottom = height + "px"; | |
| this.element.style.height = height + "px"; | |
| this._view.doResize(); | |
| }, | |
| immediatelyFinishAnimation: function() | |
| { | |
| if (this._currentAnimation) | |
| this._currentAnimation.forceComplete(); | |
| }, | |
| _animationDuration: function(animationType) | |
| { | |
| switch (animationType) { | |
| case WebInspector.Drawer.AnimationType.Slow: | |
| return 2000; | |
| case WebInspector.Drawer.AnimationType.Normal: | |
| return 250; | |
| default: | |
| return 0; | |
| } | |
| }, | |
| _startStatusBarDragging: function(event) | |
| { | |
| if (!this.visible || event.target !== this._floatingStatusBarContainer) | |
| return false; | |
| this._view.storeScrollPositions(); | |
| this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop(); | |
| return true; | |
| }, | |
| _statusBarDragging: function(event) | |
| { | |
| var height = window.innerHeight - event.pageY + this._statusBarDragOffset; | |
| height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop() - Preferences.minConsoleHeight); | |
| this._mainElement.style.bottom = height + "px"; | |
| this.element.style.height = height + "px"; | |
| if (WebInspector.inspectorView.currentPanel()) | |
| WebInspector.inspectorView.currentPanel().doResize(); | |
| this._view.doResize(); | |
| event.consume(true); | |
| }, | |
| _endStatusBarDragging: function(event) | |
| { | |
| this._savedHeight = this.element.offsetHeight; | |
| delete this._statusBarDragOffset; | |
| event.consume(); | |
| } | |
| } | |
| WebInspector.drawer = null; | |
| WebInspector.ConsoleModel = function() | |
| { | |
| this.messages = []; | |
| this.warnings = 0; | |
| this.errors = 0; | |
| this._interruptRepeatCount = false; | |
| InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleDispatcher(this)); | |
| } | |
| WebInspector.ConsoleModel.Events = { | |
| ConsoleCleared: "console-cleared", | |
| MessageAdded: "console-message-added", | |
| RepeatCountUpdated: "repeat-count-updated" | |
| } | |
| WebInspector.ConsoleModel.prototype = { | |
| enableAgent: function() | |
| { | |
| if (WebInspector.settings.monitoringXHREnabled.get()) | |
| ConsoleAgent.setMonitoringXHREnabled(true); | |
| this._enablingConsole = true; | |
| function callback() | |
| { | |
| delete this._enablingConsole; | |
| } | |
| ConsoleAgent.enable(callback.bind(this)); | |
| }, | |
| enablingConsole: function() | |
| { | |
| return !!this._enablingConsole; | |
| }, | |
| addMessage: function(msg) | |
| { | |
| this.messages.push(msg); | |
| this._previousMessage = msg; | |
| this._incrementErrorWarningCount(msg); | |
| this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, msg); | |
| this._interruptRepeatCount = false; | |
| }, | |
| _incrementErrorWarningCount: function(msg) | |
| { | |
| switch (msg.level) { | |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: | |
| this.warnings += msg.repeatDelta; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Error: | |
| this.errors += msg.repeatDelta; | |
| break; | |
| } | |
| }, | |
| requestClearMessages: function() | |
| { | |
| ConsoleAgent.clearMessages(); | |
| this.clearMessages(); | |
| }, | |
| clearMessages: function() | |
| { | |
| this.messages = []; | |
| this.errors = 0; | |
| this.warnings = 0; | |
| this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared); | |
| }, | |
| interruptRepeatCount: function() | |
| { | |
| this._interruptRepeatCount = true; | |
| }, | |
| _messageRepeatCountUpdated: function(count) | |
| { | |
| var msg = this._previousMessage; | |
| if (!msg) | |
| return; | |
| var prevRepeatCount = msg.totalRepeatCount; | |
| if (!this._interruptRepeatCount) { | |
| msg.repeatDelta = count - prevRepeatCount; | |
| msg.repeatCount = msg.repeatCount + msg.repeatDelta; | |
| msg.totalRepeatCount = count; | |
| msg.updateRepeatCount(); | |
| this._incrementErrorWarningCount(msg); | |
| this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.RepeatCountUpdated, msg); | |
| } else { | |
| var msgCopy = msg.clone(); | |
| msgCopy.totalRepeatCount = count; | |
| msgCopy.repeatCount = (count - prevRepeatCount) || 1; | |
| msgCopy.repeatDelta = msgCopy.repeatCount; | |
| this.addMessage(msgCopy); | |
| } | |
| } | |
| } | |
| WebInspector.ConsoleModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.ConsoleMessage = function(source, level, url, line, repeatCount) | |
| { | |
| this.source = source; | |
| this.level = level; | |
| this.url = url || null; | |
| this.line = line || 0; | |
| this.message = ""; | |
| repeatCount = repeatCount || 1; | |
| this.repeatCount = repeatCount; | |
| this.repeatDelta = repeatCount; | |
| this.totalRepeatCount = repeatCount; | |
| } | |
| WebInspector.ConsoleMessage.prototype = { | |
| isErrorOrWarning: function() | |
| { | |
| return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error); | |
| }, | |
| updateRepeatCount: function() | |
| { | |
| }, | |
| clone: function() | |
| { | |
| }, | |
| location: function() | |
| { | |
| } | |
| } | |
| WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, requestId, isOutdated) | |
| { | |
| } | |
| WebInspector.ConsoleMessage.MessageSource = { | |
| HTML: "html", | |
| XML: "xml", | |
| JS: "javascript", | |
| Network: "network", | |
| ConsoleAPI: "console-api", | |
| Other: "other" | |
| } | |
| WebInspector.ConsoleMessage.MessageType = { | |
| Log: "log", | |
| Dir: "dir", | |
| DirXML: "dirxml", | |
| Trace: "trace", | |
| StartGroup: "startGroup", | |
| StartGroupCollapsed: "startGroupCollapsed", | |
| EndGroup: "endGroup", | |
| Assert: "assert", | |
| Result: "result" | |
| } | |
| WebInspector.ConsoleMessage.MessageLevel = { | |
| Tip: "tip", | |
| Log: "log", | |
| Warning: "warning", | |
| Error: "error", | |
| Debug: "debug" | |
| } | |
| WebInspector.ConsoleDispatcher = function(console) | |
| { | |
| this._console = console; | |
| } | |
| WebInspector.ConsoleDispatcher.prototype = { | |
| messageAdded: function(payload) | |
| { | |
| var consoleMessage = WebInspector.ConsoleMessage.create( | |
| payload.source, | |
| payload.level, | |
| payload.text, | |
| payload.type, | |
| payload.url, | |
| payload.line, | |
| payload.repeatCount, | |
| payload.parameters, | |
| payload.stackTrace, | |
| payload.networkRequestId, | |
| this._console._enablingConsole); | |
| this._console.addMessage(consoleMessage); | |
| }, | |
| messageRepeatCountUpdated: function(count) | |
| { | |
| this._console._messageRepeatCountUpdated(count); | |
| }, | |
| messagesCleared: function() | |
| { | |
| if (!WebInspector.settings.preserveConsoleLog.get()) | |
| this._console.clearMessages(); | |
| } | |
| } | |
| WebInspector.console = null; | |
| WebInspector.ConsoleMessageImpl = function(source, level, message, linkifier, type, url, line, repeatCount, parameters, stackTrace, requestId, isOutdated) | |
| { | |
| WebInspector.ConsoleMessage.call(this, source, level, url, line, repeatCount); | |
| this._linkifier = linkifier; | |
| this.type = type || WebInspector.ConsoleMessage.MessageType.Log; | |
| this._messageText = message; | |
| this._parameters = parameters; | |
| this._stackTrace = stackTrace; | |
| this._request = requestId ? WebInspector.networkLog.requestForId(requestId) : null; | |
| this._isOutdated = isOutdated; | |
| this._customFormatters = { | |
| "object": this._formatParameterAsObject, | |
| "array": this._formatParameterAsArray, | |
| "node": this._formatParameterAsNode, | |
| "string": this._formatParameterAsString | |
| }; | |
| } | |
| WebInspector.ConsoleMessageImpl.prototype = { | |
| _formatMessage: function() | |
| { | |
| this._formattedMessage = document.createElement("span"); | |
| this._formattedMessage.className = "console-message-text source-code"; | |
| if (this.source === WebInspector.ConsoleMessage.MessageSource.ConsoleAPI) { | |
| switch (this.type) { | |
| case WebInspector.ConsoleMessage.MessageType.Trace: | |
| this._messageElement = document.createTextNode("console.trace()"); | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.Assert: | |
| var args = [WebInspector.UIString("Assertion failed:")]; | |
| if (this._parameters) | |
| args = args.concat(this._parameters); | |
| this._messageElement = this._format(args); | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.Dir: | |
| var obj = this._parameters ? this._parameters[0] : undefined; | |
| var args = ["%O", obj]; | |
| this._messageElement = this._format(args); | |
| break; | |
| default: | |
| var args = this._parameters || [this._messageText]; | |
| this._messageElement = this._format(args); | |
| } | |
| } else if (this.source === WebInspector.ConsoleMessage.MessageSource.Network) { | |
| if (this._request) { | |
| this._stackTrace = this._request.initiator.stackTrace; | |
| if (this._request.initiator && this._request.initiator.url) { | |
| this.url = this._request.initiator.url; | |
| this.line = this._request.initiator.lineNumber; | |
| } | |
| this._messageElement = document.createElement("span"); | |
| if (this.level === WebInspector.ConsoleMessage.MessageLevel.Error) { | |
| this._messageElement.appendChild(document.createTextNode(this._request.requestMethod + " ")); | |
| this._messageElement.appendChild(WebInspector.linkifyRequestAsNode(this._request)); | |
| if (this._request.failed) | |
| this._messageElement.appendChild(document.createTextNode(" " + this._request.localizedFailDescription)); | |
| else | |
| this._messageElement.appendChild(document.createTextNode(" " + this._request.statusCode + " (" + this._request.statusText + ")")); | |
| } else { | |
| var fragment = WebInspector.linkifyStringAsFragmentWithCustomLinkifier(this._messageText, WebInspector.linkifyRequestAsNode.bind(null, this._request, "")); | |
| this._messageElement.appendChild(fragment); | |
| } | |
| } else { | |
| if (this.url) { | |
| var isExternal = !WebInspector.resourceForURL(this.url); | |
| this._anchorElement = WebInspector.linkifyURLAsNode(this.url, this.url, "console-message-url", isExternal); | |
| } | |
| this._messageElement = this._format([this._messageText]); | |
| } | |
| } else { | |
| var args = this._parameters || [this._messageText]; | |
| this._messageElement = this._format(args); | |
| } | |
| if (this.source !== WebInspector.ConsoleMessage.MessageSource.Network || this._request) { | |
| if (this._stackTrace && this._stackTrace.length && this._stackTrace[0].url) { | |
| this._anchorElement = this._linkifyCallFrame(this._stackTrace[0]); | |
| } else if (this.url && this.url !== "undefined") { | |
| this._anchorElement = this._linkifyLocation(this.url, this.line, 0); | |
| } | |
| } | |
| this._formattedMessage.appendChild(this._messageElement); | |
| if (this._anchorElement) { | |
| this._formattedMessage.appendChild(document.createTextNode(" ")); | |
| this._formattedMessage.appendChild(this._anchorElement); | |
| } | |
| var dumpStackTrace = !!this._stackTrace && this._stackTrace.length && (this.source === WebInspector.ConsoleMessage.MessageSource.Network || this.level === WebInspector.ConsoleMessage.MessageLevel.Error || this.type === WebInspector.ConsoleMessage.MessageType.Trace); | |
| if (dumpStackTrace) { | |
| var ol = document.createElement("ol"); | |
| ol.className = "outline-disclosure"; | |
| var treeOutline = new TreeOutline(ol); | |
| var content = this._formattedMessage; | |
| var root = new TreeElement(content, null, true); | |
| content.treeElementForTest = root; | |
| treeOutline.appendChild(root); | |
| if (this.type === WebInspector.ConsoleMessage.MessageType.Trace) | |
| root.expand(); | |
| this._populateStackTraceTreeElement(root); | |
| this._formattedMessage = ol; | |
| } | |
| this._message = this._messageElement.textContent; | |
| }, | |
| get message() | |
| { | |
| var formattedMessage = this.formattedMessage; | |
| return this._message; | |
| }, | |
| get formattedMessage() | |
| { | |
| if (!this._formattedMessage) | |
| this._formatMessage(); | |
| return this._formattedMessage; | |
| }, | |
| _linkifyLocation: function(url, lineNumber, columnNumber) | |
| { | |
| lineNumber = lineNumber ? lineNumber - 1 : 0; | |
| columnNumber = columnNumber ? columnNumber - 1 : 0; | |
| return this._linkifier.linkifyLocation(url, lineNumber, columnNumber, "console-message-url"); | |
| }, | |
| _linkifyCallFrame: function(callFrame) | |
| { | |
| return this._linkifyLocation(callFrame.url, callFrame.lineNumber, callFrame.columnNumber); | |
| }, | |
| isErrorOrWarning: function() | |
| { | |
| return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error); | |
| }, | |
| _format: function(parameters) | |
| { | |
| var formattedResult = document.createElement("span"); | |
| if (!parameters.length) | |
| return formattedResult; | |
| for (var i = 0; i < parameters.length; ++i) { | |
| if (parameters[i] instanceof WebInspector.RemoteObject) | |
| continue; | |
| if (typeof parameters[i] === "object") | |
| parameters[i] = WebInspector.RemoteObject.fromPayload(parameters[i]); | |
| else | |
| parameters[i] = WebInspector.RemoteObject.fromPrimitiveValue(parameters[i]); | |
| } | |
| var shouldFormatMessage = WebInspector.RemoteObject.type(parameters[0]) === "string" && this.type !== WebInspector.ConsoleMessage.MessageType.Result; | |
| if (shouldFormatMessage) { | |
| var result = this._formatWithSubstitutionString(parameters, formattedResult); | |
| parameters = result.unusedSubstitutions; | |
| if (parameters.length) | |
| formattedResult.appendChild(document.createTextNode(" ")); | |
| } | |
| for (var i = 0; i < parameters.length; ++i) { | |
| if (shouldFormatMessage && parameters[i].type === "string") | |
| formattedResult.appendChild(document.createTextNode(parameters[i].description)); | |
| else | |
| formattedResult.appendChild(this._formatParameter(parameters[i], false, true)); | |
| if (i < parameters.length - 1) | |
| formattedResult.appendChild(document.createTextNode(" ")); | |
| } | |
| return formattedResult; | |
| }, | |
| _formatParameter: function(output, forceObjectFormat, includePreview) | |
| { | |
| var type; | |
| if (forceObjectFormat) | |
| type = "object"; | |
| else if (output instanceof WebInspector.RemoteObject) | |
| type = output.subtype || output.type; | |
| else | |
| type = typeof output; | |
| var formatter = this._customFormatters[type]; | |
| if (!formatter) { | |
| formatter = this._formatParameterAsValue; | |
| output = output.description; | |
| } | |
| var span = document.createElement("span"); | |
| span.className = "console-formatted-" + type + " source-code"; | |
| formatter.call(this, output, span, includePreview); | |
| return span; | |
| }, | |
| _formatParameterAsValue: function(val, elem) | |
| { | |
| elem.appendChild(document.createTextNode(val)); | |
| }, | |
| _formatParameterAsObject: function(obj, elem, includePreview) | |
| { | |
| this._formatParameterAsArrayOrObject(obj, obj.description, elem, includePreview); | |
| }, | |
| _formatParameterAsArrayOrObject: function(obj, description, elem, includePreview) | |
| { | |
| var titleElement = document.createElement("span"); | |
| if (description) | |
| titleElement.createTextChild(description); | |
| if (includePreview && obj.preview) { | |
| titleElement.addStyleClass("console-object-preview"); | |
| var lossless = this._appendObjectPreview(obj, description, titleElement); | |
| if (lossless) { | |
| elem.appendChild(titleElement); | |
| return; | |
| } | |
| } | |
| var section = new WebInspector.ObjectPropertiesSection(obj, titleElement); | |
| section.enableContextMenu(); | |
| elem.appendChild(section.element); | |
| }, | |
| _appendObjectPreview: function(obj, description, titleElement) | |
| { | |
| var preview = obj.preview; | |
| var isArray = obj.subtype === "array"; | |
| if (description) | |
| titleElement.createTextChild(" "); | |
| titleElement.createTextChild(isArray ? "[" : "{"); | |
| for (var i = 0; i < preview.properties.length; ++i) { | |
| if (i > 0) | |
| titleElement.createTextChild(", "); | |
| var property = preview.properties[i]; | |
| if (!isArray || property.name != i) { | |
| titleElement.createChild("span", "name").textContent = property.name; | |
| titleElement.createTextChild(": "); | |
| } | |
| var span = titleElement.createChild("span", "console-formatted-" + property.type); | |
| if (property.type === "object") { | |
| if (property.subtype === "node") | |
| span.addStyleClass("console-formatted-preview-node"); | |
| else if (property.subtype === "regexp") | |
| span.addStyleClass("console-formatted-string"); | |
| } | |
| span.textContent = property.value; | |
| } | |
| if (preview.overflow) | |
| titleElement.createChild("span").textContent = "\u2026"; | |
| titleElement.createTextChild(isArray ? "]" : "}"); | |
| return preview.lossless; | |
| }, | |
| _formatParameterAsNode: function(object, elem) | |
| { | |
| function printNode(nodeId) | |
| { | |
| if (!nodeId) { | |
| this._formatParameterAsObject(object, elem, false); | |
| return; | |
| } | |
| var treeOutline = new WebInspector.ElementsTreeOutline(false, false, true); | |
| treeOutline.setVisible(true); | |
| treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); | |
| treeOutline.element.addStyleClass("outline-disclosure"); | |
| if (!treeOutline.children[0].hasChildren) | |
| treeOutline.element.addStyleClass("single-node"); | |
| elem.appendChild(treeOutline.element); | |
| treeOutline.element.treeElementForTest = treeOutline.children[0]; | |
| } | |
| object.pushNodeToFrontend(printNode.bind(this)); | |
| }, | |
| _formatParameterAsArray: function(array, elem) | |
| { | |
| if (array.preview) { | |
| this._formatParameterAsArrayOrObject(array, "", elem, true); | |
| return; | |
| } | |
| const maxFlatArrayLength = 100; | |
| if (this._isOutdated || array.arrayLength() > maxFlatArrayLength) | |
| this._formatParameterAsObject(array, elem, false); | |
| else | |
| array.getOwnProperties(this._printArray.bind(this, array, elem)); | |
| }, | |
| _formatParameterAsString: function(output, elem) | |
| { | |
| var span = document.createElement("span"); | |
| span.className = "console-formatted-string source-code"; | |
| span.appendChild(WebInspector.linkifyStringAsFragment(output.description)); | |
| elem.removeStyleClass("console-formatted-string"); | |
| elem.appendChild(document.createTextNode("\"")); | |
| elem.appendChild(span); | |
| elem.appendChild(document.createTextNode("\"")); | |
| }, | |
| _printArray: function(array, elem, properties) | |
| { | |
| if (!properties) | |
| return; | |
| var elements = []; | |
| for (var i = 0; i < properties.length; ++i) { | |
| var property = properties[i]; | |
| var name = property.name; | |
| if (!isNaN(name)) | |
| elements[name] = this._formatAsArrayEntry(property.value); | |
| } | |
| elem.appendChild(document.createTextNode("[")); | |
| var lastNonEmptyIndex = -1; | |
| function appendUndefined(elem, index) | |
| { | |
| if (index - lastNonEmptyIndex <= 1) | |
| return; | |
| var span = elem.createChild(span, "console-formatted-undefined"); | |
| span.textContent = WebInspector.UIString("undefined × %d", index - lastNonEmptyIndex - 1); | |
| } | |
| var length = array.arrayLength(); | |
| for (var i = 0; i < length; ++i) { | |
| var element = elements[i]; | |
| if (!element) | |
| continue; | |
| if (i - lastNonEmptyIndex > 1) { | |
| appendUndefined(elem, i); | |
| elem.appendChild(document.createTextNode(", ")); | |
| } | |
| elem.appendChild(element); | |
| lastNonEmptyIndex = i; | |
| if (i < length - 1) | |
| elem.appendChild(document.createTextNode(", ")); | |
| } | |
| appendUndefined(elem, length); | |
| elem.appendChild(document.createTextNode("]")); | |
| }, | |
| _formatAsArrayEntry: function(output) | |
| { | |
| return this._formatParameter(output, output.subtype && output.subtype === "array", false); | |
| }, | |
| _formatWithSubstitutionString: function(parameters, formattedResult) | |
| { | |
| var formatters = {} | |
| function parameterFormatter(force, obj) | |
| { | |
| return this._formatParameter(obj, force, false); | |
| } | |
| function valueFormatter(obj) | |
| { | |
| return obj.description; | |
| } | |
| formatters.o = parameterFormatter.bind(this, false); | |
| formatters.s = valueFormatter; | |
| formatters.f = valueFormatter; | |
| formatters.i = valueFormatter; | |
| formatters.d = valueFormatter; | |
| formatters.O = parameterFormatter.bind(this, true); | |
| function append(a, b) | |
| { | |
| if (!(b instanceof Node)) | |
| a.appendChild(WebInspector.linkifyStringAsFragment(b.toString())); | |
| else | |
| a.appendChild(b); | |
| return a; | |
| } | |
| return String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append); | |
| }, | |
| clearHighlight: function() | |
| { | |
| if (!this._formattedMessage) | |
| return; | |
| var highlightedMessage = this._formattedMessage; | |
| delete this._formattedMessage; | |
| delete this._anchorElement; | |
| delete this._messageElement; | |
| this._formatMessage(); | |
| this._element.replaceChild(this._formattedMessage, highlightedMessage); | |
| }, | |
| highlightSearchResults: function(regexObject) | |
| { | |
| if (!this._formattedMessage) | |
| return; | |
| this._highlightSearchResultsInElement(regexObject, this._messageElement); | |
| if (this._anchorElement) | |
| this._highlightSearchResultsInElement(regexObject, this._anchorElement); | |
| this._element.scrollIntoViewIfNeeded(); | |
| }, | |
| _highlightSearchResultsInElement: function(regexObject, element) | |
| { | |
| regexObject.lastIndex = 0; | |
| var text = element.textContent; | |
| var match = regexObject.exec(text); | |
| var offset = 0; | |
| var matchRanges = []; | |
| while (match) { | |
| matchRanges.push({ offset: match.index, length: match[0].length }); | |
| match = regexObject.exec(text); | |
| } | |
| WebInspector.highlightSearchResults(element, matchRanges); | |
| }, | |
| matchesRegex: function(regexObject) | |
| { | |
| return regexObject.test(this._message) || (this._anchorElement && regexObject.test(this._anchorElement.textContent)); | |
| }, | |
| toMessageElement: function() | |
| { | |
| if (this._element) | |
| return this._element; | |
| var element = document.createElement("div"); | |
| element.message = this; | |
| element.className = "console-message"; | |
| this._element = element; | |
| switch (this.level) { | |
| case WebInspector.ConsoleMessage.MessageLevel.Tip: | |
| element.addStyleClass("console-tip-level"); | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Log: | |
| element.addStyleClass("console-log-level"); | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Debug: | |
| element.addStyleClass("console-debug-level"); | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: | |
| element.addStyleClass("console-warning-level"); | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Error: | |
| element.addStyleClass("console-error-level"); | |
| break; | |
| } | |
| if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup || this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) | |
| element.addStyleClass("console-group-title"); | |
| element.appendChild(this.formattedMessage); | |
| if (this.repeatCount > 1) | |
| this.updateRepeatCount(); | |
| return element; | |
| }, | |
| _populateStackTraceTreeElement: function(parentTreeElement) | |
| { | |
| for (var i = 0; i < this._stackTrace.length; i++) { | |
| var frame = this._stackTrace[i]; | |
| var content = document.createElement("div"); | |
| var messageTextElement = document.createElement("span"); | |
| messageTextElement.className = "console-message-text source-code"; | |
| var functionName = frame.functionName || WebInspector.UIString("(anonymous function)"); | |
| messageTextElement.appendChild(document.createTextNode(functionName)); | |
| content.appendChild(messageTextElement); | |
| if (frame.url) { | |
| content.appendChild(document.createTextNode(" ")); | |
| var urlElement = this._linkifyCallFrame(frame); | |
| content.appendChild(urlElement); | |
| } | |
| var treeElement = new TreeElement(content); | |
| parentTreeElement.appendChild(treeElement); | |
| } | |
| }, | |
| updateRepeatCount: function() { | |
| if (!this.repeatCountElement) { | |
| this.repeatCountElement = document.createElement("span"); | |
| this.repeatCountElement.className = "bubble"; | |
| this._element.insertBefore(this.repeatCountElement, this._element.firstChild); | |
| this._element.addStyleClass("repeated-message"); | |
| } | |
| this.repeatCountElement.textContent = this.repeatCount; | |
| }, | |
| toString: function() | |
| { | |
| var sourceString; | |
| switch (this.source) { | |
| case WebInspector.ConsoleMessage.MessageSource.HTML: | |
| sourceString = "HTML"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageSource.XML: | |
| sourceString = "XML"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageSource.JS: | |
| sourceString = "JS"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageSource.Network: | |
| sourceString = "Network"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageSource.ConsoleAPI: | |
| sourceString = "ConsoleAPI"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageSource.Other: | |
| sourceString = "Other"; | |
| break; | |
| } | |
| var typeString; | |
| switch (this.type) { | |
| case WebInspector.ConsoleMessage.MessageType.Log: | |
| typeString = "Log"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.Dir: | |
| typeString = "Dir"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.DirXML: | |
| typeString = "Dir XML"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.Trace: | |
| typeString = "Trace"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed: | |
| case WebInspector.ConsoleMessage.MessageType.StartGroup: | |
| typeString = "Start Group"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.EndGroup: | |
| typeString = "End Group"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.Assert: | |
| typeString = "Assert"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageType.Result: | |
| typeString = "Result"; | |
| break; | |
| } | |
| var levelString; | |
| switch (this.level) { | |
| case WebInspector.ConsoleMessage.MessageLevel.Tip: | |
| levelString = "Tip"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Log: | |
| levelString = "Log"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: | |
| levelString = "Warning"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Debug: | |
| levelString = "Debug"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Error: | |
| levelString = "Error"; | |
| break; | |
| } | |
| return sourceString + " " + typeString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line; | |
| }, | |
| get text() | |
| { | |
| return this._messageText; | |
| }, | |
| location: function() | |
| { | |
| var lineNumber = this.stackTrace ? this.stackTrace[0].lineNumber - 1 : this.line - 1; | |
| var columnNumber = this.stackTrace && this.stackTrace[0].columnNumber ? this.stackTrace[0].columnNumber - 1 : 0; | |
| return WebInspector.debuggerModel.createRawLocationByURL(this.url, lineNumber, columnNumber); | |
| }, | |
| isEqual: function(msg) | |
| { | |
| if (!msg) | |
| return false; | |
| if (this._stackTrace) { | |
| if (!msg._stackTrace) | |
| return false; | |
| var l = this._stackTrace; | |
| var r = msg._stackTrace; | |
| for (var i = 0; i < l.length; i++) { | |
| if (l[i].url !== r[i].url || | |
| l[i].functionName !== r[i].functionName || | |
| l[i].lineNumber !== r[i].lineNumber || | |
| l[i].columnNumber !== r[i].columnNumber) | |
| return false; | |
| } | |
| } | |
| return (this.source === msg.source) | |
| && (this.type === msg.type) | |
| && (this.level === msg.level) | |
| && (this.line === msg.line) | |
| && (this.url === msg.url) | |
| && (this.message === msg.message) | |
| && (this._request === msg._request); | |
| }, | |
| get stackTrace() | |
| { | |
| return this._stackTrace; | |
| }, | |
| clone: function() | |
| { | |
| return WebInspector.ConsoleMessage.create(this.source, this.level, this._messageText, this.type, this.url, this.line, this.repeatCount, this._parameters, this._stackTrace, this._request ? this._request.requestId : undefined, this._isOutdated); | |
| } | |
| } | |
| WebInspector.ConsoleMessageImpl.prototype.__proto__ = WebInspector.ConsoleMessage.prototype; | |
| const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>"; | |
| WebInspector.ConsoleView = function(hideContextSelector) | |
| { | |
| WebInspector.View.call(this); | |
| this.element.id = "console-view"; | |
| this.messages = []; | |
| this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear console log."), "clear-status-bar-item"); | |
| this._clearConsoleButton.addEventListener("click", this._requestClearMessages, this); | |
| this._frameSelector = new WebInspector.StatusBarComboBox(this._frameChanged.bind(this), "console-context"); | |
| this._contextSelector = new WebInspector.StatusBarComboBox(this._contextChanged.bind(this), "console-context"); | |
| if (hideContextSelector) { | |
| this._frameSelector.element.addStyleClass("hidden"); | |
| this._contextSelector.element.addStyleClass("hidden"); | |
| } | |
| this.messagesElement = document.createElement("div"); | |
| this.messagesElement.id = "console-messages"; | |
| this.messagesElement.className = "monospace"; | |
| this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true); | |
| this.element.appendChild(this.messagesElement); | |
| this._scrolledToBottom = true; | |
| this.promptElement = document.createElement("div"); | |
| this.promptElement.id = "console-prompt"; | |
| this.promptElement.className = "source-code"; | |
| this.promptElement.spellcheck = false; | |
| this.messagesElement.appendChild(this.promptElement); | |
| this.messagesElement.appendChild(document.createElement("br")); | |
| this.topGroup = new WebInspector.ConsoleGroup(null); | |
| this.messagesElement.insertBefore(this.topGroup.element, this.promptElement); | |
| this.currentGroup = this.topGroup; | |
| this._filterBarElement = document.createElement("div"); | |
| this._filterBarElement.className = "scope-bar status-bar-item"; | |
| function createDividerElement() | |
| { | |
| var dividerElement = document.createElement("div"); | |
| dividerElement.addStyleClass("scope-bar-divider"); | |
| this._filterBarElement.appendChild(dividerElement); | |
| } | |
| var updateFilterHandler = this._updateFilter.bind(this); | |
| function createFilterElement(category, label) | |
| { | |
| var categoryElement = document.createElement("li"); | |
| categoryElement.category = category; | |
| categoryElement.className = category; | |
| categoryElement.addEventListener("click", updateFilterHandler, false); | |
| categoryElement.textContent = label; | |
| this._filterBarElement.appendChild(categoryElement); | |
| return categoryElement; | |
| } | |
| this.allElement = createFilterElement.call(this, "all", WebInspector.UIString("All")); | |
| createDividerElement.call(this); | |
| this.errorElement = createFilterElement.call(this, "errors", WebInspector.UIString("Errors")); | |
| this.warningElement = createFilterElement.call(this, "warnings", WebInspector.UIString("Warnings")); | |
| this.logElement = createFilterElement.call(this, "logs", WebInspector.UIString("Logs")); | |
| this.filter(this.allElement, false); | |
| this._registerShortcuts(); | |
| this.registerRequiredCSS("textPrompt.css"); | |
| this.messagesElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false); | |
| WebInspector.settings.monitoringXHREnabled.addChangeListener(this._monitoringXHREnabledSettingChanged.bind(this)); | |
| WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); | |
| WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); | |
| this._linkifier = new WebInspector.Linkifier(); | |
| this.prompt = new WebInspector.TextPromptWithHistory(this.completionsForTextPrompt.bind(this), ExpressionStopCharacters + "."); | |
| this.prompt.setSuggestBoxEnabled("generic-suggest"); | |
| this.prompt.renderAsBlock(); | |
| this.prompt.attach(this.promptElement); | |
| this.prompt.proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this), false); | |
| this.prompt.setHistoryData(WebInspector.settings.consoleHistory.get()); | |
| WebInspector.runtimeModel.contextLists().forEach(this._addFrame, this); | |
| WebInspector.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.FrameExecutionContextListAdded, this._frameAdded, this); | |
| WebInspector.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.FrameExecutionContextListRemoved, this._frameRemoved, this); | |
| } | |
| WebInspector.ConsoleView.Events = { | |
| ConsoleCleared: "console-cleared", | |
| EntryAdded: "console-entry-added", | |
| } | |
| WebInspector.ConsoleView.prototype = { | |
| get statusBarItems() | |
| { | |
| return [this._clearConsoleButton.element, this._frameSelector.element, this._contextSelector.element, this._filterBarElement]; | |
| }, | |
| _frameAdded: function(event) | |
| { | |
| var contextList = event.data; | |
| this._addFrame(contextList); | |
| }, | |
| _addFrame: function(contextList) | |
| { | |
| var option = document.createElement("option"); | |
| option.text = contextList.displayName; | |
| option.title = contextList.url; | |
| option._contextList = contextList; | |
| contextList._consoleOption = option; | |
| this._frameSelector.addOption(option); | |
| contextList.addEventListener(WebInspector.FrameExecutionContextList.EventTypes.ContextsUpdated, this._frameUpdated, this); | |
| contextList.addEventListener(WebInspector.FrameExecutionContextList.EventTypes.ContextAdded, this._contextAdded, this); | |
| this._frameChanged(); | |
| }, | |
| _frameRemoved: function(event) | |
| { | |
| var contextList = event.data; | |
| this._frameSelector.removeOption(contextList._consoleOption); | |
| this._frameChanged(); | |
| }, | |
| _frameChanged: function() | |
| { | |
| var context = this._currentFrame(); | |
| if (!context) { | |
| delete this._currentExecutionContext; | |
| this._contextSelector.element.addStyleClass("hidden"); | |
| return; | |
| } | |
| var executionContexts = context.executionContexts(); | |
| if (executionContexts.length) | |
| this._currentExecutionContext = executionContexts[0]; | |
| if (executionContexts.length === 1) { | |
| this._contextSelector.element.addStyleClass("hidden"); | |
| return; | |
| } | |
| this._contextSelector.element.removeStyleClass("hidden"); | |
| this._contextSelector.removeOptions(); | |
| for (var i = 0; i < executionContexts.length; i++) | |
| this._appendContextOption(executionContexts[i]); | |
| }, | |
| _appendContextOption: function(executionContext) | |
| { | |
| if (!this._currentExecutionContext) | |
| this._currentExecutionContext = executionContext; | |
| var option = document.createElement("option"); | |
| option.text = executionContext.name; | |
| option.title = executionContext.id; | |
| option._executionContext = executionContext; | |
| this._contextSelector.addOption(option); | |
| }, | |
| _contextChanged: function(event) | |
| { | |
| var option = this._contextSelector.selectedOption(); | |
| this._currentExecutionContext = option ? option._executionContext : undefined; | |
| }, | |
| _frameUpdated: function(event) | |
| { | |
| var contextList = event.data; | |
| var option = contextList._consoleOption; | |
| option.text = contextList.displayName; | |
| option.title = contextList.url; | |
| }, | |
| _contextAdded: function(event) | |
| { | |
| var contextList = event.data; | |
| if (contextList === this._currentFrame()) | |
| this._frameChanged(); | |
| }, | |
| _currentFrame: function() | |
| { | |
| var option = this._frameSelector.selectedOption(); | |
| return option ? option._contextList : undefined; | |
| }, | |
| _updateFilter: function(e) | |
| { | |
| var isMac = WebInspector.isMac(); | |
| var selectMultiple = false; | |
| if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) | |
| selectMultiple = true; | |
| if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey) | |
| selectMultiple = true; | |
| this.filter(e.target, selectMultiple); | |
| }, | |
| filter: function(target, selectMultiple) | |
| { | |
| function unselectAll() | |
| { | |
| this.allElement.removeStyleClass("selected"); | |
| this.errorElement.removeStyleClass("selected"); | |
| this.warningElement.removeStyleClass("selected"); | |
| this.logElement.removeStyleClass("selected"); | |
| this.messagesElement.removeStyleClass("filter-all"); | |
| this.messagesElement.removeStyleClass("filter-errors"); | |
| this.messagesElement.removeStyleClass("filter-warnings"); | |
| this.messagesElement.removeStyleClass("filter-logs"); | |
| } | |
| var targetFilterClass = "filter-" + target.category; | |
| if (target.category === "all") { | |
| if (target.hasStyleClass("selected")) { | |
| return; | |
| } | |
| unselectAll.call(this); | |
| } else { | |
| if (this.allElement.hasStyleClass("selected")) { | |
| this.allElement.removeStyleClass("selected"); | |
| this.messagesElement.removeStyleClass("filter-all"); | |
| } | |
| } | |
| if (!selectMultiple) { | |
| unselectAll.call(this); | |
| target.addStyleClass("selected"); | |
| this.messagesElement.addStyleClass(targetFilterClass); | |
| return; | |
| } | |
| if (target.hasStyleClass("selected")) { | |
| target.removeStyleClass("selected"); | |
| this.messagesElement.removeStyleClass(targetFilterClass); | |
| } else { | |
| target.addStyleClass("selected"); | |
| this.messagesElement.addStyleClass(targetFilterClass); | |
| } | |
| }, | |
| willHide: function() | |
| { | |
| this.prompt.hideSuggestBox(); | |
| this.prompt.clearAutoComplete(true); | |
| }, | |
| wasShown: function() | |
| { | |
| if (!this.prompt.isCaretInsidePrompt()) | |
| this.prompt.moveCaretToEndOfPrompt(); | |
| }, | |
| afterShow: function() | |
| { | |
| WebInspector.setCurrentFocusElement(this.promptElement); | |
| }, | |
| storeScrollPositions: function() | |
| { | |
| WebInspector.View.prototype.storeScrollPositions.call(this); | |
| this._scrolledToBottom = this.messagesElement.isScrolledToBottom(); | |
| }, | |
| restoreScrollPositions: function() | |
| { | |
| if (this._scrolledToBottom) | |
| this._immediatelyScrollIntoView(); | |
| else | |
| WebInspector.View.prototype.restoreScrollPositions.call(this); | |
| }, | |
| onResize: function() | |
| { | |
| this.restoreScrollPositions(); | |
| }, | |
| _isScrollIntoViewScheduled: function() | |
| { | |
| return !!this._scrollIntoViewTimer; | |
| }, | |
| _scheduleScrollIntoView: function() | |
| { | |
| if (this._scrollIntoViewTimer) | |
| return; | |
| function scrollIntoView() | |
| { | |
| delete this._scrollIntoViewTimer; | |
| this.promptElement.scrollIntoView(true); | |
| } | |
| this._scrollIntoViewTimer = setTimeout(scrollIntoView.bind(this), 20); | |
| }, | |
| _immediatelyScrollIntoView: function() | |
| { | |
| this.promptElement.scrollIntoView(true); | |
| this._cancelScheduledScrollIntoView(); | |
| }, | |
| _cancelScheduledScrollIntoView: function() | |
| { | |
| if (!this._isScrollIntoViewScheduled()) | |
| return; | |
| clearTimeout(this._scrollIntoViewTimer); | |
| delete this._scrollIntoViewTimer; | |
| }, | |
| _consoleMessageAdded: function(event) | |
| { | |
| this._appendConsoleMessage(event.data); | |
| }, | |
| _appendConsoleMessage: function(msg) | |
| { | |
| if (!this._isScrollIntoViewScheduled() && ((msg instanceof WebInspector.ConsoleCommandResult) || this.messagesElement.isScrolledToBottom())) | |
| this._scheduleScrollIntoView(); | |
| this.messages.push(msg); | |
| if (msg.type === WebInspector.ConsoleMessage.MessageType.EndGroup) { | |
| var parentGroup = this.currentGroup.parentGroup | |
| if (parentGroup) | |
| this.currentGroup = parentGroup; | |
| } else { | |
| if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) { | |
| var group = new WebInspector.ConsoleGroup(this.currentGroup); | |
| this.currentGroup.messagesElement.appendChild(group.element); | |
| this.currentGroup = group; | |
| } | |
| this.currentGroup.addMessage(msg); | |
| } | |
| this.dispatchEventToListeners(WebInspector.ConsoleView.Events.EntryAdded, msg); | |
| }, | |
| _consoleCleared: function() | |
| { | |
| this._scrolledToBottom = true; | |
| this.messages = []; | |
| this.currentGroup = this.topGroup; | |
| this.topGroup.messagesElement.removeChildren(); | |
| this.dispatchEventToListeners(WebInspector.ConsoleView.Events.ConsoleCleared); | |
| this._linkifier.reset(); | |
| }, | |
| completionsForTextPrompt: function(textPrompt, wordRange, force, completionsReadyCallback) | |
| { | |
| var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, ExpressionStopCharacters, textPrompt.proxyElement, "backward"); | |
| var expressionString = expressionRange.toString(); | |
| var prefix = wordRange.toString(); | |
| this.completionsForExpression(expressionString, prefix, force, completionsReadyCallback); | |
| }, | |
| completionsForExpression: function(expressionString, prefix, force, completionsReadyCallback) | |
| { | |
| var lastIndex = expressionString.length - 1; | |
| var dotNotation = (expressionString[lastIndex] === "."); | |
| var bracketNotation = (expressionString[lastIndex] === "["); | |
| if (dotNotation || bracketNotation) | |
| expressionString = expressionString.substr(0, lastIndex); | |
| if (expressionString && parseInt(expressionString, 10) == expressionString) { | |
| completionsReadyCallback([]); | |
| return; | |
| } | |
| if (!prefix && !expressionString && !force) { | |
| completionsReadyCallback([]); | |
| return; | |
| } | |
| if (!expressionString && WebInspector.debuggerModel.selectedCallFrame()) | |
| WebInspector.debuggerModel.getSelectedCallFrameVariables(receivedPropertyNames.bind(this)); | |
| else | |
| this.evalInInspectedWindow(expressionString, "completion", true, true, false, evaluated.bind(this)); | |
| function evaluated(result, wasThrown) | |
| { | |
| if (!result || wasThrown) { | |
| completionsReadyCallback([]); | |
| return; | |
| } | |
| function getCompletions(primitiveType) | |
| { | |
| var object; | |
| if (primitiveType === "string") | |
| object = new String(""); | |
| else if (primitiveType === "number") | |
| object = new Number(0); | |
| else if (primitiveType === "boolean") | |
| object = new Boolean(false); | |
| else | |
| object = this; | |
| var resultSet = {}; | |
| for (var o = object; o; o = o.__proto__) { | |
| try { | |
| var names = Object.getOwnPropertyNames(o); | |
| for (var i = 0; i < names.length; ++i) | |
| resultSet[names[i]] = true; | |
| } catch (e) { | |
| } | |
| } | |
| return resultSet; | |
| } | |
| if (result.type === "object" || result.type === "function") | |
| result.callFunctionJSON(getCompletions, undefined, receivedPropertyNames.bind(this)); | |
| else if (result.type === "string" || result.type === "number" || result.type === "boolean") | |
| this.evalInInspectedWindow("(" + getCompletions + ")(\"" + result.type + "\")", "completion", false, true, true, receivedPropertyNamesFromEval.bind(this)); | |
| } | |
| function receivedPropertyNamesFromEval(notRelevant, wasThrown, result) | |
| { | |
| if (result && !wasThrown) | |
| receivedPropertyNames.call(this, result.value); | |
| else | |
| completionsReadyCallback([]); | |
| } | |
| function receivedPropertyNames(propertyNames) | |
| { | |
| RuntimeAgent.releaseObjectGroup("completion"); | |
| if (!propertyNames) { | |
| completionsReadyCallback([]); | |
| return; | |
| } | |
| var includeCommandLineAPI = (!dotNotation && !bracketNotation); | |
| if (includeCommandLineAPI) { | |
| const commandLineAPI = ["dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear"]; | |
| for (var i = 0; i < commandLineAPI.length; ++i) | |
| propertyNames[commandLineAPI[i]] = true; | |
| } | |
| this._reportCompletions(completionsReadyCallback, dotNotation, bracketNotation, expressionString, prefix, Object.keys(propertyNames)); | |
| } | |
| }, | |
| _reportCompletions: function(completionsReadyCallback, dotNotation, bracketNotation, expressionString, prefix, properties) { | |
| if (bracketNotation) { | |
| if (prefix.length && prefix[0] === "'") | |
| var quoteUsed = "'"; | |
| else | |
| var quoteUsed = "\""; | |
| } | |
| var results = []; | |
| if (!expressionString) { | |
| const keywords = ["break", "case", "catch", "continue", "default", "delete", "do", "else", "finally", "for", "function", "if", "in", | |
| "instanceof", "new", "return", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with"]; | |
| properties = properties.concat(keywords); | |
| } | |
| properties.sort(); | |
| for (var i = 0; i < properties.length; ++i) { | |
| var property = properties[i]; | |
| if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property)) | |
| continue; | |
| if (bracketNotation) { | |
| if (!/^[0-9]+$/.test(property)) | |
| property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed; | |
| property += "]"; | |
| } | |
| if (property.length < prefix.length) | |
| continue; | |
| if (prefix.length && !property.startsWith(prefix)) | |
| continue; | |
| results.push(property); | |
| } | |
| completionsReadyCallback(results); | |
| }, | |
| _handleContextMenuEvent: function(event) | |
| { | |
| if (!window.getSelection().isCollapsed) { | |
| return; | |
| } | |
| if (event.target.enclosingNodeOrSelfWithNodeName("a")) | |
| return; | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| function monitoringXHRItemAction() | |
| { | |
| WebInspector.settings.monitoringXHREnabled.set(!WebInspector.settings.monitoringXHREnabled.get()); | |
| } | |
| contextMenu.appendCheckboxItem(WebInspector.UIString("Log XMLHttpRequests"), monitoringXHRItemAction.bind(this), WebInspector.settings.monitoringXHREnabled.get()); | |
| function preserveLogItemAction() | |
| { | |
| WebInspector.settings.preserveConsoleLog.set(!WebInspector.settings.preserveConsoleLog.get()); | |
| } | |
| contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Preserve log upon navigation" : "Preserve Log upon Navigation"), preserveLogItemAction.bind(this), WebInspector.settings.preserveConsoleLog.get()); | |
| contextMenu.appendSeparator(); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear console" : "Clear Console"), this._requestClearMessages.bind(this)); | |
| contextMenu.show(event); | |
| }, | |
| _monitoringXHREnabledSettingChanged: function(event) | |
| { | |
| ConsoleAgent.setMonitoringXHREnabled(event.data); | |
| }, | |
| _messagesClicked: function(event) | |
| { | |
| if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed) | |
| this.prompt.moveCaretToEndOfPrompt(); | |
| }, | |
| _registerShortcuts: function() | |
| { | |
| this._shortcuts = {}; | |
| var shortcut = WebInspector.KeyboardShortcut; | |
| if (WebInspector.isMac()) { | |
| var shortcutK = shortcut.makeDescriptor("k", WebInspector.KeyboardShortcut.Modifiers.Meta); | |
| this._shortcuts[shortcutK.key] = this._requestClearMessages.bind(this); | |
| } | |
| var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl); | |
| this._shortcuts[shortcutL.key] = this._requestClearMessages.bind(this); | |
| var shortcutM = shortcut.makeDescriptor("m", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift); | |
| this._shortcuts[shortcutM.key] = this._dumpMemory.bind(this); | |
| var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Console")); | |
| var keys = WebInspector.isMac() ? [ shortcutK.name, shortcutL.name ] : [ shortcutL.name ]; | |
| section.addAlternateKeys(keys, WebInspector.UIString("Clear console")); | |
| keys = [ | |
| shortcut.shortcutToString(shortcut.Keys.Tab), | |
| shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift) | |
| ]; | |
| section.addRelatedKeys(keys, WebInspector.UIString("Next/previous suggestion")); | |
| section.addKey(shortcut.shortcutToString(shortcut.Keys.Right), WebInspector.UIString("Accept suggestion")); | |
| keys = [ | |
| shortcut.shortcutToString(shortcut.Keys.Down), | |
| shortcut.shortcutToString(shortcut.Keys.Up) | |
| ]; | |
| section.addRelatedKeys(keys, WebInspector.UIString("Next/previous line")); | |
| keys = [ | |
| shortcut.shortcutToString("N", shortcut.Modifiers.Alt), | |
| shortcut.shortcutToString("P", shortcut.Modifiers.Alt) | |
| ]; | |
| if (WebInspector.isMac()) | |
| section.addRelatedKeys(keys, WebInspector.UIString("Next/previous command")); | |
| section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Execute command")); | |
| }, | |
| _requestClearMessages: function() | |
| { | |
| WebInspector.console.requestClearMessages(); | |
| }, | |
| _promptKeyDown: function(event) | |
| { | |
| if (isEnterKey(event)) { | |
| this._enterKeyPressed(event); | |
| return; | |
| } | |
| var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); | |
| var handler = this._shortcuts[shortcut]; | |
| if (handler) { | |
| handler(); | |
| event.preventDefault(); | |
| return; | |
| } | |
| }, | |
| evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, callback) | |
| { | |
| if (WebInspector.debuggerModel.selectedCallFrame()) { | |
| WebInspector.debuggerModel.evaluateOnSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, callback); | |
| return; | |
| } | |
| if (!expression) { | |
| expression = "this"; | |
| } | |
| function evalCallback(error, result, wasThrown) | |
| { | |
| if (error) { | |
| console.error(error); | |
| callback(null, false); | |
| return; | |
| } | |
| if (returnByValue) | |
| callback(null, !!wasThrown, wasThrown ? null : result); | |
| else | |
| callback(WebInspector.RemoteObject.fromPayload(result), !!wasThrown); | |
| } | |
| RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, this._currentExecutionContext ? this._currentExecutionContext.id : undefined, returnByValue, evalCallback); | |
| }, | |
| evaluateUsingTextPrompt: function(expression, showResultOnly) | |
| { | |
| this._appendCommand(expression, this.prompt.text, false, showResultOnly); | |
| }, | |
| _enterKeyPressed: function(event) | |
| { | |
| if (event.altKey || event.ctrlKey || event.shiftKey) | |
| return; | |
| event.consume(true); | |
| this.prompt.clearAutoComplete(true); | |
| var str = this.prompt.text; | |
| if (!str.length) | |
| return; | |
| this._appendCommand(str, "", true, false); | |
| }, | |
| runScript: function(scriptId) | |
| { | |
| DebuggerAgent.runScript(scriptId, this._currentExecutionContext ? this._currentExecutionContext.id : undefined, "console", false, runCallback.bind(this)); | |
| WebInspector.userMetrics.ConsoleEvaluated.record(); | |
| function runCallback(error, result, wasThrown) | |
| { | |
| if (error) { | |
| console.error(error); | |
| return; | |
| } | |
| this._printResult(result, wasThrown, null); | |
| } | |
| }, | |
| _printResult: function(result, wasThrown, originatingCommand) | |
| { | |
| if (!result) | |
| return; | |
| this._appendConsoleMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, originatingCommand, this._linkifier)); | |
| }, | |
| _appendCommand: function(text, newPromptText, useCommandLineAPI, showResultOnly) | |
| { | |
| if (!showResultOnly) { | |
| var commandMessage = new WebInspector.ConsoleCommand(text); | |
| WebInspector.console.interruptRepeatCount(); | |
| this._appendConsoleMessage(commandMessage); | |
| } | |
| this.prompt.text = newPromptText; | |
| function printResult(result, wasThrown) | |
| { | |
| if (!result) | |
| return; | |
| if (!showResultOnly) { | |
| this.prompt.pushHistoryItem(text); | |
| WebInspector.settings.consoleHistory.set(this.prompt.historyData.slice(-30)); | |
| } | |
| this._printResult(result, wasThrown, commandMessage); | |
| } | |
| this.evalInInspectedWindow(text, "console", useCommandLineAPI, false, false, printResult.bind(this)); | |
| WebInspector.userMetrics.ConsoleEvaluated.record(); | |
| }, | |
| elementsToRestoreScrollPositionsFor: function() | |
| { | |
| return [this.messagesElement]; | |
| }, | |
| _dumpMemory: function() | |
| { | |
| function comparator(a, b) | |
| { | |
| if (a.size < b.size) | |
| return 1; | |
| if (a.size > b.size) | |
| return -1; | |
| return a.title.localeCompare(b.title); | |
| } | |
| function callback(error, groups) | |
| { | |
| var titles = []; | |
| groups.sort(comparator); | |
| for (var i = 0; i < groups.length; ++i) { | |
| var suffix = groups[i].size > 0 ? " [" + groups[i].size + "]" : ""; | |
| titles.push(groups[i].title + suffix + (groups[i].documentURI ? " (" + groups[i].documentURI + ")" : "")); | |
| } | |
| var counter = 1; | |
| var previousTitle = null; | |
| for (var i = 0; i < titles.length; ++i) { | |
| var title = titles[i]; | |
| if (title === previousTitle) { | |
| counter++; | |
| continue; | |
| } | |
| if (previousTitle) | |
| WebInspector.log(counter > 1 ? counter + " x " + previousTitle : previousTitle); | |
| previousTitle = title; | |
| counter = 1; | |
| } | |
| WebInspector.log(counter > 1 ? counter + " x " + previousTitle : previousTitle); | |
| } | |
| MemoryAgent.getDOMNodeCount(callback); | |
| } | |
| } | |
| WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.ConsoleCommand = function(command) | |
| { | |
| this.command = command; | |
| } | |
| WebInspector.ConsoleCommand.prototype = { | |
| clearHighlight: function() | |
| { | |
| var highlightedMessage = this._formattedCommand; | |
| delete this._formattedCommand; | |
| this._formatCommand(); | |
| this._element.replaceChild(this._formattedCommand, highlightedMessage); | |
| }, | |
| highlightSearchResults: function(regexObject) | |
| { | |
| regexObject.lastIndex = 0; | |
| var text = this.command; | |
| var match = regexObject.exec(text); | |
| var offset = 0; | |
| var matchRanges = []; | |
| while (match) { | |
| matchRanges.push({ offset: match.index, length: match[0].length }); | |
| match = regexObject.exec(text); | |
| } | |
| WebInspector.highlightSearchResults(this._formattedCommand, matchRanges); | |
| this._element.scrollIntoViewIfNeeded(); | |
| }, | |
| matchesRegex: function(regexObject) | |
| { | |
| return regexObject.test(this.command); | |
| }, | |
| toMessageElement: function() | |
| { | |
| if (!this._element) { | |
| this._element = document.createElement("div"); | |
| this._element.command = this; | |
| this._element.className = "console-user-command"; | |
| this._formatCommand(); | |
| this._element.appendChild(this._formattedCommand); | |
| } | |
| return this._element; | |
| }, | |
| _formatCommand: function() | |
| { | |
| this._formattedCommand = document.createElement("span"); | |
| this._formattedCommand.className = "console-message-text source-code"; | |
| this._formattedCommand.textContent = this.command; | |
| }, | |
| } | |
| WebInspector.ConsoleCommandResult = function(result, wasThrown, originatingCommand, linkifier) | |
| { | |
| var level = (wasThrown ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log); | |
| this.originatingCommand = originatingCommand; | |
| WebInspector.ConsoleMessageImpl.call(this, WebInspector.ConsoleMessage.MessageSource.JS, level, "", linkifier, WebInspector.ConsoleMessage.MessageType.Result, undefined, undefined, undefined, [result]); | |
| } | |
| WebInspector.ConsoleCommandResult.prototype = { | |
| toMessageElement: function() | |
| { | |
| var element = WebInspector.ConsoleMessageImpl.prototype.toMessageElement.call(this); | |
| element.addStyleClass("console-user-command-result"); | |
| return element; | |
| } | |
| } | |
| WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessageImpl.prototype; | |
| WebInspector.ConsoleGroup = function(parentGroup) | |
| { | |
| this.parentGroup = parentGroup; | |
| var element = document.createElement("div"); | |
| element.className = "console-group"; | |
| element.group = this; | |
| this.element = element; | |
| if (parentGroup) { | |
| var bracketElement = document.createElement("div"); | |
| bracketElement.className = "console-group-bracket"; | |
| element.appendChild(bracketElement); | |
| } | |
| var messagesElement = document.createElement("div"); | |
| messagesElement.className = "console-group-messages"; | |
| element.appendChild(messagesElement); | |
| this.messagesElement = messagesElement; | |
| } | |
| WebInspector.ConsoleGroup.prototype = { | |
| addMessage: function(msg) | |
| { | |
| var element = msg.toMessageElement(); | |
| if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) { | |
| this.messagesElement.parentNode.insertBefore(element, this.messagesElement); | |
| element.addEventListener("click", this._titleClicked.bind(this), false); | |
| var groupElement = element.enclosingNodeOrSelfWithClass("console-group"); | |
| if (groupElement && msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) | |
| groupElement.addStyleClass("collapsed"); | |
| } else | |
| this.messagesElement.appendChild(element); | |
| if (element.previousSibling && msg.originatingCommand && element.previousSibling.command === msg.originatingCommand) | |
| element.previousSibling.addStyleClass("console-adjacent-user-command-result"); | |
| }, | |
| _titleClicked: function(event) | |
| { | |
| var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title"); | |
| if (groupTitleElement) { | |
| var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group"); | |
| if (groupElement) | |
| if (groupElement.hasStyleClass("collapsed")) | |
| groupElement.removeStyleClass("collapsed"); | |
| else | |
| groupElement.addStyleClass("collapsed"); | |
| groupTitleElement.scrollIntoViewIfNeeded(true); | |
| } | |
| event.consume(true); | |
| } | |
| } | |
| WebInspector.consoleView = null; | |
| WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, requestId, isOutdated) | |
| { | |
| return new WebInspector.ConsoleMessageImpl(source, level, message, WebInspector.consoleView._linkifier, type, url, line, repeatCount, parameters, stackTrace, requestId, isOutdated); | |
| } | |
| WebInspector.Panel = function(name) | |
| { | |
| WebInspector.View.call(this); | |
| WebInspector.panels[name] = this; | |
| this.element.addStyleClass("panel"); | |
| this.element.addStyleClass(name); | |
| this._panelName = name; | |
| this._shortcuts = {}; | |
| WebInspector.settings[this._sidebarWidthSettingName()] = WebInspector.settings.createSetting(this._sidebarWidthSettingName(), undefined); | |
| } | |
| WebInspector.Panel.counterRightMargin = 25; | |
| WebInspector.Panel.prototype = { | |
| get name() | |
| { | |
| return this._panelName; | |
| }, | |
| show: function() | |
| { | |
| WebInspector.View.prototype.show.call(this, WebInspector.inspectorView.panelsElement()); | |
| }, | |
| wasShown: function() | |
| { | |
| var statusBarItems = this.statusBarItems; | |
| if (statusBarItems) { | |
| this._statusBarItemContainer = document.createElement("div"); | |
| for (var i = 0; i < statusBarItems.length; ++i) | |
| this._statusBarItemContainer.appendChild(statusBarItems[i]); | |
| document.getElementById("panel-status-bar").appendChild(this._statusBarItemContainer); | |
| } | |
| this.focus(); | |
| }, | |
| willHide: function() | |
| { | |
| if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode) | |
| this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer); | |
| delete this._statusBarItemContainer; | |
| }, | |
| reset: function() | |
| { | |
| this.searchCanceled(); | |
| }, | |
| defaultFocusedElement: function() | |
| { | |
| return this.sidebarTreeElement || this.element; | |
| }, | |
| searchCanceled: function() | |
| { | |
| WebInspector.searchController.updateSearchMatchesCount(0, this); | |
| }, | |
| performSearch: function(query) | |
| { | |
| this.searchCanceled(); | |
| }, | |
| jumpToNextSearchResult: function() | |
| { | |
| }, | |
| jumpToPreviousSearchResult: function() | |
| { | |
| }, | |
| canSearchAndReplace: function() | |
| { | |
| return false; | |
| }, | |
| replaceSelectionWith: function(text) | |
| { | |
| }, | |
| replaceAllWith: function(query, text) | |
| { | |
| }, | |
| canFilter: function() | |
| { | |
| return false; | |
| }, | |
| performFilter: function(query) | |
| { | |
| }, | |
| createSplitView: function(parentElement, position, defaultWidth) | |
| { | |
| if (this.splitView) | |
| return; | |
| if (!parentElement) | |
| parentElement = this.element; | |
| this.splitView = new WebInspector.SplitView(position || WebInspector.SplitView.SidebarPosition.Left, this._sidebarWidthSettingName(), defaultWidth); | |
| this.splitView.show(parentElement); | |
| this.splitView.addEventListener(WebInspector.SplitView.EventTypes.Resized, this.sidebarResized.bind(this)); | |
| this.sidebarElement = this.splitView.sidebarElement; | |
| }, | |
| createSplitViewWithSidebarTree: function(parentElement, position, defaultWidth) | |
| { | |
| if (this.splitView) | |
| return; | |
| this.createSplitView(parentElement, position); | |
| this.sidebarTreeElement = document.createElement("ol"); | |
| this.sidebarTreeElement.className = "sidebar-tree"; | |
| this.splitView.sidebarElement.appendChild(this.sidebarTreeElement); | |
| this.splitView.sidebarElement.addStyleClass("sidebar"); | |
| this.sidebarTree = new TreeOutline(this.sidebarTreeElement); | |
| this.sidebarTree.panel = this; | |
| }, | |
| _sidebarWidthSettingName: function() | |
| { | |
| return this._panelName + "SidebarWidth"; | |
| }, | |
| get statusBarItems() | |
| { | |
| }, | |
| sidebarResized: function(width) | |
| { | |
| }, | |
| statusBarResized: function() | |
| { | |
| }, | |
| canShowAnchorLocation: function(anchor) | |
| { | |
| return false; | |
| }, | |
| showAnchorLocation: function(anchor) | |
| { | |
| }, | |
| elementsToRestoreScrollPositionsFor: function() | |
| { | |
| return []; | |
| }, | |
| handleShortcut: function(event) | |
| { | |
| var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); | |
| var handler = this._shortcuts[shortcutKey]; | |
| if (handler) { | |
| handler(event); | |
| event.handled = true; | |
| } | |
| }, | |
| registerShortcut: function(key, handler) | |
| { | |
| this._shortcuts[key] = handler; | |
| }, | |
| unregisterShortcut: function(key) | |
| { | |
| delete this._shortcuts[key]; | |
| } | |
| } | |
| WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.PanelDescriptor = function(name, title, className, scriptName, panel) | |
| { | |
| this._name = name; | |
| this._title = title; | |
| this._className = className; | |
| this._scriptName = scriptName; | |
| this._panel = panel; | |
| } | |
| WebInspector.PanelDescriptor.prototype = { | |
| name: function() | |
| { | |
| return this._name; | |
| }, | |
| title: function() | |
| { | |
| return this._title; | |
| }, | |
| iconURL: function() | |
| { | |
| return this._iconURL; | |
| }, | |
| setIconURL: function(iconURL) | |
| { | |
| this._iconURL = iconURL; | |
| }, | |
| panel: function() | |
| { | |
| if (this._panel) | |
| return this._panel; | |
| if (this._scriptName) | |
| importScript(this._scriptName); | |
| this._panel = new WebInspector[this._className]; | |
| return this._panel; | |
| } | |
| } | |
| WebInspector.InspectorView = function() | |
| { | |
| WebInspector.View.call(this); | |
| this.markAsRoot(); | |
| this.element.id = "main-panels"; | |
| this.element.setAttribute("spellcheck", false); | |
| this._history = []; | |
| this._historyIterator = -1; | |
| document.addEventListener("keydown", this._keyDown.bind(this), false); | |
| document.addEventListener("keypress", this._keyPress.bind(this), false); | |
| this._panelOrder = []; | |
| this._panelDescriptors = {}; | |
| this._openBracketIdentifiers = ["U+005B", "U+00DB"].keySet(); | |
| this._closeBracketIdentifiers = ["U+005D", "U+00DD"].keySet(); | |
| this._footerElementContainer = this.element.createChild("div", "inspector-footer status-bar hidden"); | |
| this._panelsElement = this.element.createChild("div", "fill"); | |
| } | |
| WebInspector.InspectorView.Events = { | |
| PanelSelected: "PanelSelected" | |
| } | |
| WebInspector.InspectorView.prototype = { | |
| addPanel: function(panelDescriptor) | |
| { | |
| this._panelOrder.push(panelDescriptor.name()); | |
| this._panelDescriptors[panelDescriptor.name()] = panelDescriptor; | |
| WebInspector.toolbar.addPanel(panelDescriptor); | |
| }, | |
| panel: function(panelName) | |
| { | |
| var panelDescriptor = this._panelDescriptors[panelName]; | |
| if (!panelDescriptor && this._panelOrder.length) | |
| panelDescriptor = this._panelDescriptors[this._panelOrder[0]]; | |
| return panelDescriptor ? panelDescriptor.panel() : null; | |
| }, | |
| showPanel: function(panelName) | |
| { | |
| var panel = this.panel(panelName); | |
| if (panel) | |
| this.setCurrentPanel(panel); | |
| return panel; | |
| }, | |
| currentPanel: function() | |
| { | |
| return this._currentPanel; | |
| }, | |
| setCurrentPanel: function(x) | |
| { | |
| if (this._currentPanel === x) | |
| return; | |
| if (this._currentPanel) | |
| this._currentPanel.detach(); | |
| this._currentPanel = x; | |
| if (x) { | |
| x.show(); | |
| this.dispatchEventToListeners(WebInspector.InspectorView.Events.PanelSelected); | |
| WebInspector.searchController.cancelSearch(); | |
| } | |
| for (var panelName in WebInspector.panels) { | |
| if (WebInspector.panels[panelName] === x) { | |
| WebInspector.settings.lastActivePanel.set(panelName); | |
| this._pushToHistory(panelName); | |
| WebInspector.userMetrics.panelShown(panelName); | |
| } | |
| } | |
| }, | |
| _keyPress: function(event) | |
| { | |
| clearTimeout(this._keyDownTimer); | |
| delete this._keyDownTimer; | |
| }, | |
| _keyDown: function(event) | |
| { | |
| if (!WebInspector.isWin() || (!this._openBracketIdentifiers.hasOwnProperty(event.keyIdentifier) && !this._closeBracketIdentifiers.hasOwnProperty(event.keyIdentifier))) { | |
| this._keyDownInternal(event); | |
| return; | |
| } | |
| this._keyDownTimer = setTimeout(this._keyDownInternal.bind(this, event), 0); | |
| }, | |
| _keyDownInternal: function(event) | |
| { | |
| if (this._openBracketIdentifiers.hasOwnProperty(event.keyIdentifier)) { | |
| var isRotateLeft = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && !event.altKey; | |
| if (isRotateLeft) { | |
| var index = this._panelOrder.indexOf(this.currentPanel().name); | |
| index = (index === 0) ? this._panelOrder.length - 1 : index - 1; | |
| this.showPanel(this._panelOrder[index]); | |
| event.consume(true); | |
| return; | |
| } | |
| var isGoBack = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && event.altKey; | |
| if (isGoBack && this._canGoBackInHistory()) { | |
| this._goBackInHistory(); | |
| event.consume(true); | |
| } | |
| return; | |
| } | |
| if (this._closeBracketIdentifiers.hasOwnProperty(event.keyIdentifier)) { | |
| var isRotateRight = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && !event.altKey; | |
| if (isRotateRight) { | |
| var index = this._panelOrder.indexOf(this.currentPanel().name); | |
| index = (index + 1) % this._panelOrder.length; | |
| this.showPanel(this._panelOrder[index]); | |
| event.consume(true); | |
| return; | |
| } | |
| var isGoForward = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && event.altKey; | |
| if (isGoForward && this._canGoForwardInHistory()) { | |
| this._goForwardInHistory(); | |
| event.consume(true); | |
| } | |
| return; | |
| } | |
| }, | |
| _canGoBackInHistory: function() | |
| { | |
| return this._historyIterator > 0; | |
| }, | |
| _goBackInHistory: function() | |
| { | |
| this._inHistory = true; | |
| this.setCurrentPanel(WebInspector.panels[this._history[--this._historyIterator]]); | |
| delete this._inHistory; | |
| }, | |
| _canGoForwardInHistory: function() | |
| { | |
| return this._historyIterator < this._history.length - 1; | |
| }, | |
| _goForwardInHistory: function() | |
| { | |
| this._inHistory = true; | |
| this.setCurrentPanel(WebInspector.panels[this._history[++this._historyIterator]]); | |
| delete this._inHistory; | |
| }, | |
| _pushToHistory: function(panelName) | |
| { | |
| if (this._inHistory) | |
| return; | |
| this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1); | |
| if (!this._history.length || this._history[this._history.length - 1] !== panelName) | |
| this._history.push(panelName); | |
| this._historyIterator = this._history.length - 1; | |
| }, | |
| panelsElement: function() | |
| { | |
| return this._panelsElement; | |
| }, | |
| setFooterElement: function(element) | |
| { | |
| if (element) { | |
| this._footerElementContainer.removeStyleClass("hidden"); | |
| this._footerElementContainer.appendChild(element); | |
| this._panelsElement.style.bottom = this._footerElementContainer.offsetHeight + "px"; | |
| } else { | |
| this._footerElementContainer.addStyleClass("hidden"); | |
| this._footerElementContainer.removeChildren(); | |
| this._panelsElement.style.bottom = 0; | |
| } | |
| this.doResize(); | |
| }, | |
| showPanelForAnchorNavigation: function(panel) | |
| { | |
| WebInspector.searchController.disableSearchUntilExplicitAction(); | |
| this.setCurrentPanel(panel); | |
| } | |
| } | |
| WebInspector.InspectorView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.inspectorView = null; | |
| WebInspector.AdvancedSearchController = function() | |
| { | |
| this._shortcut = WebInspector.AdvancedSearchController.createShortcut(); | |
| this._searchId = 0; | |
| WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false)); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); | |
| } | |
| WebInspector.AdvancedSearchController.createShortcut = function() | |
| { | |
| if (WebInspector.isMac()) | |
| return WebInspector.KeyboardShortcut.makeDescriptor("f", WebInspector.KeyboardShortcut.Modifiers.Meta | WebInspector.KeyboardShortcut.Modifiers.Alt); | |
| else | |
| return WebInspector.KeyboardShortcut.makeDescriptor("f", WebInspector.KeyboardShortcut.Modifiers.Ctrl | WebInspector.KeyboardShortcut.Modifiers.Shift); | |
| } | |
| WebInspector.AdvancedSearchController.prototype = { | |
| handleShortcut: function(event) | |
| { | |
| if (WebInspector.KeyboardShortcut.makeKeyFromEvent(event) === this._shortcut.key) { | |
| if (!this._searchView || !this._searchView.isShowing() || this._searchView._search !== document.activeElement) { | |
| WebInspector.showPanel("scripts"); | |
| this.show(); | |
| } else | |
| this.close(); | |
| event.consume(true); | |
| return true; | |
| } | |
| return false; | |
| }, | |
| _frameNavigated: function() | |
| { | |
| this.resetSearch(); | |
| }, | |
| registerSearchScope: function(searchScope) | |
| { | |
| this._searchScope = searchScope; | |
| }, | |
| show: function() | |
| { | |
| if (!this._searchView) | |
| this._searchView = new WebInspector.SearchView(this); | |
| if (this._searchView.isShowing()) | |
| this._searchView.focus(); | |
| else | |
| WebInspector.showViewInDrawer(this._searchView._searchPanelElement, this._searchView, this.stopSearch.bind(this)); | |
| }, | |
| close: function() | |
| { | |
| this.stopSearch(); | |
| WebInspector.closeViewInDrawer(); | |
| }, | |
| _onSearchResult: function(searchId, searchResult) | |
| { | |
| if (searchId !== this._searchId) | |
| return; | |
| this._searchView.addSearchResult(searchResult); | |
| if (!searchResult.searchMatches.length) | |
| return; | |
| if (!this._searchResultsPane) | |
| this._searchResultsPane = this._currentSearchScope.createSearchResultsPane(this._searchConfig); | |
| this._searchView.resultsPane = this._searchResultsPane; | |
| this._searchResultsPane.addSearchResult(searchResult); | |
| }, | |
| _onSearchFinished: function(searchId, finished) | |
| { | |
| if (searchId !== this._searchId) | |
| return; | |
| if (!this._searchResultsPane) | |
| this._searchView.nothingFound(); | |
| this._searchView.searchFinished(finished); | |
| }, | |
| startSearch: function(searchConfig) | |
| { | |
| this.resetSearch(); | |
| ++this._searchId; | |
| this._searchConfig = searchConfig; | |
| this._currentSearchScope = this._searchScope; | |
| var totalSearchResultsCount = this._currentSearchScope.performSearch(searchConfig, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId)); | |
| this._searchView.searchStarted(totalSearchResultsCount); | |
| }, | |
| resetSearch: function() | |
| { | |
| this.stopSearch(); | |
| if (this._searchResultsPane) { | |
| this._searchView.resetResults(); | |
| delete this._searchResultsPane; | |
| } | |
| }, | |
| stopSearch: function() | |
| { | |
| if (this._currentSearchScope) | |
| this._currentSearchScope.stopSearch(); | |
| } | |
| } | |
| WebInspector.SearchView = function(controller) | |
| { | |
| WebInspector.View.call(this); | |
| this.registerRequiredCSS("textEditor.css"); | |
| this._controller = controller; | |
| this.element.className = "search-view"; | |
| this._searchPanelElement = document.createElement("span"); | |
| this._searchPanelElement.className = "search-drawer-header"; | |
| this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false); | |
| this._searchResultsElement = this.element.createChild("div"); | |
| this._searchResultsElement.className = "search-results"; | |
| this._searchLabel = this._searchPanelElement.createChild("span"); | |
| this._searchLabel.textContent = WebInspector.UIString("Search sources"); | |
| this._search = this._searchPanelElement.createChild("input"); | |
| this._search.setAttribute("type", "search"); | |
| this._search.addStyleClass("search-config-search"); | |
| this._search.setAttribute("results", "0"); | |
| this._search.setAttribute("size", 30); | |
| this._ignoreCaseLabel = this._searchPanelElement.createChild("label"); | |
| this._ignoreCaseLabel.addStyleClass("search-config-label"); | |
| this._ignoreCaseCheckbox = this._ignoreCaseLabel.createChild("input"); | |
| this._ignoreCaseCheckbox.setAttribute("type", "checkbox"); | |
| this._ignoreCaseCheckbox.addStyleClass("search-config-checkbox"); | |
| this._ignoreCaseLabel.appendChild(document.createTextNode(WebInspector.UIString("Ignore case"))); | |
| this._regexLabel = this._searchPanelElement.createChild("label"); | |
| this._regexLabel.addStyleClass("search-config-label"); | |
| this._regexCheckbox = this._regexLabel.createChild("input"); | |
| this._regexCheckbox.setAttribute("type", "checkbox"); | |
| this._regexCheckbox.addStyleClass("search-config-checkbox"); | |
| this._regexLabel.appendChild(document.createTextNode(WebInspector.UIString("Regular expression"))); | |
| this._searchStatusBarElement = document.createElement("div"); | |
| this._searchStatusBarElement.className = "search-status-bar-item"; | |
| this._searchMessageElement = this._searchStatusBarElement.createChild("div"); | |
| this._searchMessageElement.className = "search-status-bar-message"; | |
| this._searchResultsMessageElement = document.createElement("span"); | |
| this._searchResultsMessageElement.className = "search-results-status-bar-message"; | |
| this._load(); | |
| } | |
| WebInspector.SearchView.maxQueriesCount = 20; | |
| WebInspector.SearchView.prototype = { | |
| __proto__: WebInspector.View.prototype, | |
| get statusBarItems() | |
| { | |
| return [this._searchStatusBarElement, this._searchResultsMessageElement]; | |
| }, | |
| get searchConfig() | |
| { | |
| return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked); | |
| }, | |
| set resultsPane(resultsPane) | |
| { | |
| this.resetResults(); | |
| this._searchResultsElement.appendChild(resultsPane.element); | |
| }, | |
| searchStarted: function(totalSearchResultsCount) | |
| { | |
| this.resetResults(); | |
| this._resetCounters(); | |
| this._searchMessageElement.textContent = WebInspector.UIString("Searching..."); | |
| this._progressIndicator = new WebInspector.ProgressIndicator(); | |
| this._progressIndicator.setTotalWork(totalSearchResultsCount); | |
| this._progressIndicator.show(this._searchStatusBarElement); | |
| this._updateSearchResultsMessage(); | |
| if (!this._searchingView) | |
| this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching...")); | |
| this._searchingView.show(this._searchResultsElement); | |
| }, | |
| _updateSearchResultsMessage: function() | |
| { | |
| if (this._searchMatchesCount && this._searchResultsCount) | |
| this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount); | |
| else | |
| this._searchResultsMessageElement.textContent = ""; | |
| }, | |
| resetResults: function() | |
| { | |
| if (this._searchingView) | |
| this._searchingView.detach(); | |
| if (this._notFoundView) | |
| this._notFoundView.detach(); | |
| this._searchResultsElement.removeChildren(); | |
| }, | |
| _resetCounters: function() | |
| { | |
| this._searchMatchesCount = 0; | |
| this._searchResultsCount = 0; | |
| this._nonEmptySearchResultsCount = 0; | |
| }, | |
| nothingFound: function() | |
| { | |
| this.resetResults(); | |
| if (!this._notFoundView) | |
| this._notFoundView = new WebInspector.EmptyView(WebInspector.UIString("No matches found.")); | |
| this._notFoundView.show(this._searchResultsElement); | |
| this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found."); | |
| }, | |
| addSearchResult: function(searchResult) | |
| { | |
| this._searchMatchesCount += searchResult.searchMatches.length; | |
| this._searchResultsCount++; | |
| if (searchResult.searchMatches.length) | |
| this._nonEmptySearchResultsCount++; | |
| this._updateSearchResultsMessage(); | |
| if (this._progressIndicator.isCanceled()) | |
| this._onCancel(); | |
| else | |
| this._progressIndicator.setWorked(this._searchResultsCount); | |
| }, | |
| searchFinished: function(finished) | |
| { | |
| this._progressIndicator.done(); | |
| this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted."); | |
| }, | |
| focus: function() | |
| { | |
| WebInspector.setCurrentFocusElement(this._search); | |
| this._search.select(); | |
| }, | |
| wasShown: function() | |
| { | |
| this.focus(); | |
| }, | |
| willHide: function() | |
| { | |
| this._controller.stopSearch(); | |
| }, | |
| _onKeyDown: function(event) | |
| { | |
| switch (event.keyCode) { | |
| case WebInspector.KeyboardShortcut.Keys.Enter.code: | |
| this._onAction(); | |
| break; | |
| case WebInspector.KeyboardShortcut.Keys.Esc.code: | |
| this._controller.close(); | |
| event.consume(true); | |
| break; | |
| } | |
| }, | |
| _save: function() | |
| { | |
| var searchConfig = new WebInspector.SearchConfig(this.searchConfig.query, this.searchConfig.ignoreCase, this.searchConfig.isRegex); | |
| WebInspector.settings.advancedSearchConfig.set(searchConfig); | |
| }, | |
| _load: function() | |
| { | |
| var searchConfig = WebInspector.settings.advancedSearchConfig.get(); | |
| this._search.value = searchConfig.query; | |
| this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase; | |
| this._regexCheckbox.checked = searchConfig.isRegex; | |
| }, | |
| _onCancel: function() | |
| { | |
| this._controller.stopSearch(); | |
| this.focus(); | |
| }, | |
| _onAction: function() | |
| { | |
| if (!this.searchConfig.query || !this.searchConfig.query.length) | |
| return; | |
| this._save(); | |
| this._controller.startSearch(this.searchConfig); | |
| } | |
| } | |
| WebInspector.SearchConfig = function(query, ignoreCase, isRegex) | |
| { | |
| this.query = query; | |
| this.ignoreCase = ignoreCase; | |
| this.isRegex = isRegex; | |
| } | |
| WebInspector.SearchScope = function() | |
| { | |
| } | |
| WebInspector.SearchScope.prototype = { | |
| performSearch: function(searchConfig, searchResultCallback, searchFinishedCallback) { }, | |
| stopSearch: function() { }, | |
| createSearchResultsPane: function(searchConfig) { } | |
| } | |
| WebInspector.SearchResult = function(offset, length) | |
| { | |
| this.offset = offset; | |
| this.length = length; | |
| } | |
| WebInspector.SearchResultsPane = function(searchConfig) | |
| { | |
| this._searchConfig = searchConfig; | |
| this.element = document.createElement("div"); | |
| } | |
| WebInspector.SearchResultsPane.prototype = { | |
| get searchConfig() | |
| { | |
| return this._searchConfig; | |
| }, | |
| addSearchResult: function(searchResult) { } | |
| } | |
| WebInspector.FileBasedSearchResultsPane = function(searchConfig) | |
| { | |
| WebInspector.SearchResultsPane.call(this, searchConfig); | |
| this._searchResults = []; | |
| this.element.id ="search-results-pane-file-based"; | |
| this._treeOutlineElement = document.createElement("ol"); | |
| this._treeOutlineElement.className = "search-results-outline-disclosure"; | |
| this.element.appendChild(this._treeOutlineElement); | |
| this._treeOutline = new TreeOutline(this._treeOutlineElement); | |
| this._matchesExpandedCount = 0; | |
| } | |
| WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20; | |
| WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20; | |
| WebInspector.FileBasedSearchResultsPane.prototype = { | |
| _createAnchor: function(uiSourceCode, lineNumber, columnNumber) | |
| { | |
| var anchor = document.createElement("a"); | |
| anchor.preferredPanel = "scripts"; | |
| anchor.href = sanitizeHref(uiSourceCode.url); | |
| anchor.uiSourceCode = uiSourceCode; | |
| anchor.lineNumber = lineNumber; | |
| return anchor; | |
| }, | |
| addSearchResult: function(searchResult) | |
| { | |
| this._searchResults.push(searchResult); | |
| var uiSourceCode = searchResult.uiSourceCode; | |
| var searchMatches = searchResult.searchMatches; | |
| var fileTreeElement = this._addFileTreeElement(uiSourceCode.url, searchMatches.length, this._searchResults.length - 1); | |
| }, | |
| _fileTreeElementExpanded: function(searchResult, fileTreeElement) | |
| { | |
| if (fileTreeElement._initialized) | |
| return; | |
| var toIndex = Math.min(searchResult.searchMatches.length, WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce); | |
| if (toIndex < searchResult.searchMatches.length) { | |
| this._appendSearchMatches(fileTreeElement, searchResult, 0, toIndex - 1); | |
| this._appendShowMoreMatchesElement(fileTreeElement, searchResult, toIndex - 1); | |
| } else | |
| this._appendSearchMatches(fileTreeElement, searchResult, 0, toIndex); | |
| fileTreeElement._initialized = true; | |
| }, | |
| _appendSearchMatches: function(fileTreeElement, searchResult, fromIndex, toIndex) | |
| { | |
| var uiSourceCode = searchResult.uiSourceCode; | |
| var searchMatches = searchResult.searchMatches; | |
| var regex = createSearchRegex(this._searchConfig.query, !this._searchConfig.ignoreCase, this._searchConfig.isRegex); | |
| for (var i = fromIndex; i < toIndex; ++i) { | |
| var lineNumber = searchMatches[i].lineNumber; | |
| var lineContent = searchMatches[i].lineContent; | |
| var matchRanges = this._regexMatchRanges(lineContent, regex); | |
| var anchor = this._createAnchor(uiSourceCode, lineNumber, matchRanges[0].offset); | |
| var numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4); | |
| var lineNumberSpan = document.createElement("span"); | |
| lineNumberSpan.addStyleClass("webkit-line-number"); | |
| lineNumberSpan.addStyleClass("search-match-line-number"); | |
| lineNumberSpan.textContent = numberString; | |
| anchor.appendChild(lineNumberSpan); | |
| var contentSpan = this._createContentSpan(lineContent, matchRanges); | |
| anchor.appendChild(contentSpan); | |
| var searchMatchElement = new TreeElement("", null, false); | |
| fileTreeElement.appendChild(searchMatchElement); | |
| searchMatchElement.listItemElement.className = "search-match source-code"; | |
| searchMatchElement.listItemElement.appendChild(anchor); | |
| } | |
| }, | |
| _appendShowMoreMatchesElement: function(fileTreeElement, searchResult, startMatchIndex) | |
| { | |
| var matchesLeftCount = searchResult.searchMatches.length - startMatchIndex; | |
| var showMoreMatchesText = WebInspector.UIString("Show all matches (%d more).", matchesLeftCount); | |
| var showMoreMatchesElement = new TreeElement(showMoreMatchesText, null, false); | |
| fileTreeElement.appendChild(showMoreMatchesElement); | |
| showMoreMatchesElement.listItemElement.addStyleClass("show-more-matches"); | |
| showMoreMatchesElement.onselect = this._showMoreMatchesElementSelected.bind(this, searchResult, startMatchIndex, showMoreMatchesElement); | |
| }, | |
| _showMoreMatchesElementSelected: function(searchResult, startMatchIndex, showMoreMatchesElement) | |
| { | |
| var fileTreeElement = showMoreMatchesElement.parent; | |
| fileTreeElement.removeChild(showMoreMatchesElement); | |
| this._appendSearchMatches(fileTreeElement, searchResult, startMatchIndex, searchResult.searchMatches.length); | |
| }, | |
| _addFileTreeElement: function(fileName, searchMatchesCount, searchResultIndex) | |
| { | |
| var fileTreeElement = new TreeElement("", null, true); | |
| fileTreeElement.toggleOnClick = true; | |
| fileTreeElement.selectable = false; | |
| this._treeOutline.appendChild(fileTreeElement); | |
| fileTreeElement.listItemElement.addStyleClass("search-result"); | |
| var fileNameSpan = document.createElement("span"); | |
| fileNameSpan.className = "search-result-file-name"; | |
| fileNameSpan.textContent = fileName; | |
| fileTreeElement.listItemElement.appendChild(fileNameSpan); | |
| var matchesCountSpan = document.createElement("span"); | |
| matchesCountSpan.className = "search-result-matches-count"; | |
| if (searchMatchesCount === 1) | |
| matchesCountSpan.textContent = WebInspector.UIString("(%d match)", searchMatchesCount); | |
| else | |
| matchesCountSpan.textContent = WebInspector.UIString("(%d matches)", searchMatchesCount); | |
| fileTreeElement.listItemElement.appendChild(matchesCountSpan); | |
| var searchResult = this._searchResults[searchResultIndex]; | |
| fileTreeElement.onexpand = this._fileTreeElementExpanded.bind(this, searchResult, fileTreeElement); | |
| if (this._matchesExpandedCount < WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount) | |
| fileTreeElement.expand(); | |
| this._matchesExpandedCount += searchResult.searchMatches.length; | |
| return fileTreeElement; | |
| }, | |
| _regexMatchRanges: function(lineContent, regex) | |
| { | |
| regex.lastIndex = 0; | |
| var match; | |
| var offset = 0; | |
| var matchRanges = []; | |
| while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineContent))) | |
| matchRanges.push(new WebInspector.SearchResult(match.index, match[0].length)); | |
| return matchRanges; | |
| }, | |
| _createContentSpan: function(lineContent, matchRanges) | |
| { | |
| var contentSpan = document.createElement("span"); | |
| contentSpan.className = "search-match-content"; | |
| contentSpan.textContent = lineContent; | |
| WebInspector.highlightRangesWithStyleClass(contentSpan, matchRanges, "highlighted-match"); | |
| return contentSpan; | |
| } | |
| } | |
| WebInspector.FileBasedSearchResultsPane.prototype.__proto__ = WebInspector.SearchResultsPane.prototype; | |
| WebInspector.FileBasedSearchResultsPane.SearchResult = function(uiSourceCode, searchMatches) { | |
| this.uiSourceCode = uiSourceCode; | |
| this.searchMatches = searchMatches; | |
| } | |
| WebInspector.advancedSearchController = null; | |
| WebInspector.TimelineGrid = function() | |
| { | |
| this.element = document.createElement("div"); | |
| this._itemsGraphsElement = document.createElement("div"); | |
| this._itemsGraphsElement.id = "resources-graphs"; | |
| this.element.appendChild(this._itemsGraphsElement); | |
| this._dividersElement = document.createElement("div"); | |
| this._dividersElement.className = "resources-dividers"; | |
| this.element.appendChild(this._dividersElement); | |
| this._gridHeaderElement = document.createElement("div"); | |
| this._eventDividersElement = document.createElement("div"); | |
| this._eventDividersElement.className = "resources-event-dividers"; | |
| this._gridHeaderElement.appendChild(this._eventDividersElement); | |
| this._dividersLabelBarElement = document.createElement("div"); | |
| this._dividersLabelBarElement.className = "resources-dividers-label-bar"; | |
| this._gridHeaderElement.appendChild(this._dividersLabelBarElement); | |
| this.element.appendChild(this._gridHeaderElement); | |
| } | |
| WebInspector.TimelineGrid.prototype = { | |
| get itemsGraphsElement() | |
| { | |
| return this._itemsGraphsElement; | |
| }, | |
| get dividersElement() | |
| { | |
| return this._dividersElement; | |
| }, | |
| get dividersLabelBarElement() | |
| { | |
| return this._dividersLabelBarElement; | |
| }, | |
| get gridHeaderElement() | |
| { | |
| return this._gridHeaderElement; | |
| }, | |
| removeDividers: function() | |
| { | |
| this._dividersElement.removeChildren(); | |
| this._dividersLabelBarElement.removeChildren(); | |
| }, | |
| updateDividers: function(calculator) | |
| { | |
| var dividersElementClientWidth = this._dividersElement.clientWidth; | |
| var dividerCount = Math.round(dividersElementClientWidth / 64); | |
| var slice = calculator.boundarySpan() / dividerCount; | |
| this._currentDividerSlice = slice; | |
| var divider = this._dividersElement.firstChild; | |
| var dividerLabelBar = this._dividersLabelBarElement.firstChild; | |
| var paddingLeft = calculator.paddingLeft; | |
| for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) { | |
| if (!divider) { | |
| divider = document.createElement("div"); | |
| divider.className = "resources-divider"; | |
| this._dividersElement.appendChild(divider); | |
| dividerLabelBar = document.createElement("div"); | |
| dividerLabelBar.className = "resources-divider"; | |
| var label = document.createElement("div"); | |
| label.className = "resources-divider-label"; | |
| dividerLabelBar._labelElement = label; | |
| dividerLabelBar.appendChild(label); | |
| this._dividersLabelBarElement.appendChild(dividerLabelBar); | |
| } | |
| if (i === (paddingLeft ? 0 : 1)) { | |
| divider.addStyleClass("first"); | |
| dividerLabelBar.addStyleClass("first"); | |
| } else { | |
| divider.removeStyleClass("first"); | |
| dividerLabelBar.removeStyleClass("first"); | |
| } | |
| if (i === dividerCount) { | |
| divider.addStyleClass("last"); | |
| dividerLabelBar.addStyleClass("last"); | |
| } else { | |
| divider.removeStyleClass("last"); | |
| dividerLabelBar.removeStyleClass("last"); | |
| } | |
| var left; | |
| if (!slice) { | |
| left = dividersElementClientWidth / dividerCount * i + paddingLeft; | |
| dividerLabelBar._labelElement.textContent = ""; | |
| } else { | |
| left = calculator.computePosition(calculator.minimumBoundary() + slice * i); | |
| dividerLabelBar._labelElement.textContent = calculator.formatTime(slice * i); | |
| } | |
| var percentLeft = 100 * left / dividersElementClientWidth; | |
| this._setDividerAndBarLeft(divider, dividerLabelBar, percentLeft); | |
| divider = divider.nextSibling; | |
| dividerLabelBar = dividerLabelBar.nextSibling; | |
| } | |
| while (divider) { | |
| var nextDivider = divider.nextSibling; | |
| this._dividersElement.removeChild(divider); | |
| divider = nextDivider; | |
| } | |
| while (dividerLabelBar) { | |
| var nextDivider = dividerLabelBar.nextSibling; | |
| this._dividersLabelBarElement.removeChild(dividerLabelBar); | |
| dividerLabelBar = nextDivider; | |
| } | |
| return true; | |
| }, | |
| _setDividerAndBarLeft: function(divider, dividerLabelBar, percentLeft) | |
| { | |
| var percentStyleLeft = parseFloat(divider.style.left); | |
| if (!isNaN(percentStyleLeft) && Math.abs(percentStyleLeft - percentLeft) < 0.1) | |
| return; | |
| divider.style.left = percentLeft + "%"; | |
| dividerLabelBar.style.left = percentLeft + "%"; | |
| }, | |
| addEventDivider: function(divider) | |
| { | |
| this._eventDividersElement.appendChild(divider); | |
| }, | |
| addEventDividers: function(dividers) | |
| { | |
| this._gridHeaderElement.removeChild(this._eventDividersElement); | |
| for (var i = 0; i < dividers.length; ++i) { | |
| if (dividers[i]) | |
| this._eventDividersElement.appendChild(dividers[i]); | |
| } | |
| this._gridHeaderElement.appendChild(this._eventDividersElement); | |
| }, | |
| removeEventDividers: function() | |
| { | |
| this._eventDividersElement.removeChildren(); | |
| }, | |
| hideEventDividers: function() | |
| { | |
| this._eventDividersElement.addStyleClass("hidden"); | |
| }, | |
| showEventDividers: function() | |
| { | |
| this._eventDividersElement.removeStyleClass("hidden"); | |
| }, | |
| setScrollAndDividerTop: function(scrollTop, dividersTop) | |
| { | |
| this._dividersElement.style.top = scrollTop + "px"; | |
| } | |
| } | |
| WebInspector.TimelineGrid.Calculator = function() { } | |
| WebInspector.TimelineGrid.Calculator.prototype = { | |
| computePosition: function(time) { }, | |
| formatTime: function(time) { }, | |
| minimumBoundary: function() { }, | |
| maximumBoundary: function() { }, | |
| boundarySpan: function() { } | |
| } | |
| WebInspector.ContentProvider = function() { } | |
| WebInspector.ContentProvider.prototype = { | |
| contentURL: function() { }, | |
| contentType: function() { }, | |
| requestContent: function(callback) { }, | |
| searchInContent: function(query, caseSensitive, isRegex, callback) { } | |
| } | |
| WebInspector.ContentProvider.SearchMatch = function(lineNumber, lineContent) { | |
| this.lineNumber = lineNumber; | |
| this.lineContent = lineContent; | |
| } | |
| WebInspector.Resource = function(request, url, documentURL, frameId, loaderId, type, mimeType, isHidden) | |
| { | |
| this._request = request; | |
| this.url = url; | |
| this._documentURL = documentURL; | |
| this._frameId = frameId; | |
| this._loaderId = loaderId; | |
| this._type = type || WebInspector.resourceTypes.Other; | |
| this._mimeType = mimeType; | |
| this._isHidden = isHidden; | |
| this._content; | |
| this._contentEncoded; | |
| this._pendingContentCallbacks = []; | |
| if (this._request && !this._request.finished) | |
| this._request.addEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._requestFinished, this); | |
| } | |
| WebInspector.Resource.Events = { | |
| MessageAdded: "message-added", | |
| MessagesCleared: "messages-cleared", | |
| } | |
| WebInspector.Resource.prototype = { | |
| get request() | |
| { | |
| return this._request; | |
| }, | |
| get url() | |
| { | |
| return this._url; | |
| }, | |
| set url(x) | |
| { | |
| this._url = x; | |
| this._parsedURL = new WebInspector.ParsedURL(x); | |
| }, | |
| get parsedURL() | |
| { | |
| return this._parsedURL; | |
| }, | |
| get documentURL() | |
| { | |
| return this._documentURL; | |
| }, | |
| get frameId() | |
| { | |
| return this._frameId; | |
| }, | |
| get loaderId() | |
| { | |
| return this._loaderId; | |
| }, | |
| get displayName() | |
| { | |
| return this._parsedURL.displayName; | |
| }, | |
| get type() | |
| { | |
| return this._request ? this._request.type : this._type; | |
| }, | |
| get mimeType() | |
| { | |
| return this._request ? this._request.mimeType : this._mimeType; | |
| }, | |
| get messages() | |
| { | |
| return this._messages || []; | |
| }, | |
| addMessage: function(msg) | |
| { | |
| if (!msg.isErrorOrWarning() || !msg.message) | |
| return; | |
| if (!this._messages) | |
| this._messages = []; | |
| this._messages.push(msg); | |
| this.dispatchEventToListeners(WebInspector.Resource.Events.MessageAdded, msg); | |
| }, | |
| get errors() | |
| { | |
| return this._errors || 0; | |
| }, | |
| set errors(x) | |
| { | |
| this._errors = x; | |
| }, | |
| get warnings() | |
| { | |
| return this._warnings || 0; | |
| }, | |
| set warnings(x) | |
| { | |
| this._warnings = x; | |
| }, | |
| clearErrorsAndWarnings: function() | |
| { | |
| this._messages = []; | |
| this._warnings = 0; | |
| this._errors = 0; | |
| this.dispatchEventToListeners(WebInspector.Resource.Events.MessagesCleared); | |
| }, | |
| get content() | |
| { | |
| return this._content; | |
| }, | |
| get contentEncoded() | |
| { | |
| return this._contentEncoded; | |
| }, | |
| contentURL: function() | |
| { | |
| return this._url; | |
| }, | |
| contentType: function() | |
| { | |
| return this.type; | |
| }, | |
| requestContent: function(callback) | |
| { | |
| if (typeof this._content !== "undefined") { | |
| callback(this._content, !!this._contentEncoded, this.canonicalMimeType()); | |
| return; | |
| } | |
| this._pendingContentCallbacks.push(callback); | |
| if (!this._request || this._request.finished) | |
| this._innerRequestContent(); | |
| }, | |
| canonicalMimeType: function() | |
| { | |
| return this.type.canonicalMimeType() || this.mimeType; | |
| }, | |
| searchInContent: function(query, caseSensitive, isRegex, callback) | |
| { | |
| function callbackWrapper(error, searchMatches) | |
| { | |
| callback(searchMatches || []); | |
| } | |
| if (this.frameId) | |
| PageAgent.searchInResource(this.frameId, this.url, query, caseSensitive, isRegex, callbackWrapper); | |
| else | |
| callback([]); | |
| }, | |
| populateImageSource: function(image) | |
| { | |
| function onResourceContent() | |
| { | |
| image.src = this._contentURL(); | |
| } | |
| this.requestContent(onResourceContent.bind(this)); | |
| }, | |
| _contentURL: function() | |
| { | |
| const maxDataUrlSize = 1024 * 1024; | |
| if (this._content == null || this._content.length > maxDataUrlSize) | |
| return this.url; | |
| return "data:" + this.mimeType + (this._contentEncoded ? ";base64," : ",") + this._content; | |
| }, | |
| _requestFinished: function() | |
| { | |
| this._request.removeEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._requestFinished, this); | |
| if (this._pendingContentCallbacks.length) | |
| this._innerRequestContent(); | |
| }, | |
| _innerRequestContent: function() | |
| { | |
| if (this._contentRequested) | |
| return; | |
| this._contentRequested = true; | |
| function contentLoaded(content, contentEncoded) | |
| { | |
| this._content = content; | |
| this._contentEncoded = contentEncoded; | |
| var callbacks = this._pendingContentCallbacks.slice(); | |
| for (var i = 0; i < callbacks.length; ++i) | |
| callbacks[i](this._content, this._contentEncoded, this.canonicalMimeType()); | |
| this._pendingContentCallbacks.length = 0; | |
| delete this._contentRequested; | |
| } | |
| function resourceContentLoaded(error, content, contentEncoded) | |
| { | |
| if (error) | |
| console.error("Resource content request failed: " + error); | |
| contentLoaded.call(this, error ? null : content, contentEncoded); | |
| } | |
| if (this.request) { | |
| function requestContentLoaded(content, contentEncoded, mimeType) | |
| { | |
| contentLoaded.call(this, content, contentEncoded); | |
| } | |
| this.request.requestContent(requestContentLoaded.bind(this)); | |
| return; | |
| } | |
| PageAgent.getResourceContent(this.frameId, this.url, resourceContentLoaded.bind(this)); | |
| }, | |
| isHidden: function() | |
| { | |
| return !!this._isHidden; | |
| } | |
| } | |
| WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.NetworkRequest = function(requestId, url, documentURL, frameId, loaderId) | |
| { | |
| this._requestId = requestId; | |
| this.url = url; | |
| this._documentURL = documentURL; | |
| this._frameId = frameId; | |
| this._loaderId = loaderId; | |
| this._startTime = -1; | |
| this._endTime = -1; | |
| this.statusCode = 0; | |
| this.statusText = ""; | |
| this.requestMethod = ""; | |
| this.requestTime = 0; | |
| this.receiveHeadersEnd = 0; | |
| this._type = WebInspector.resourceTypes.Other; | |
| this._content = undefined; | |
| this._contentEncoded = false; | |
| this._pendingContentCallbacks = []; | |
| this._frames = []; | |
| } | |
| WebInspector.NetworkRequest.Events = { | |
| FinishedLoading: "FinishedLoading", | |
| TimingChanged: "TimingChanged", | |
| RequestHeadersChanged: "RequestHeadersChanged", | |
| ResponseHeadersChanged: "ResponseHeadersChanged", | |
| } | |
| WebInspector.NetworkRequest.prototype = { | |
| get requestId() | |
| { | |
| return this._requestId; | |
| }, | |
| set requestId(requestId) | |
| { | |
| this._requestId = requestId; | |
| }, | |
| get url() | |
| { | |
| return this._url; | |
| }, | |
| set url(x) | |
| { | |
| if (this._url === x) | |
| return; | |
| this._url = x; | |
| this._parsedURL = new WebInspector.ParsedURL(x); | |
| delete this._parsedQueryParameters; | |
| }, | |
| get documentURL() | |
| { | |
| return this._documentURL; | |
| }, | |
| get parsedURL() | |
| { | |
| return this._parsedURL; | |
| }, | |
| get frameId() | |
| { | |
| return this._frameId; | |
| }, | |
| get loaderId() | |
| { | |
| return this._loaderId; | |
| }, | |
| get startTime() | |
| { | |
| return this._startTime || -1; | |
| }, | |
| set startTime(x) | |
| { | |
| this._startTime = x; | |
| }, | |
| get responseReceivedTime() | |
| { | |
| return this._responseReceivedTime || -1; | |
| }, | |
| set responseReceivedTime(x) | |
| { | |
| this._responseReceivedTime = x; | |
| }, | |
| get endTime() | |
| { | |
| return this._endTime || -1; | |
| }, | |
| set endTime(x) | |
| { | |
| if (this.timing && this.timing.requestTime) { | |
| this._endTime = Math.max(x, this.responseReceivedTime); | |
| } else { | |
| this._endTime = x; | |
| if (this._responseReceivedTime > x) | |
| this._responseReceivedTime = x; | |
| } | |
| }, | |
| get duration() | |
| { | |
| if (this._endTime === -1 || this._startTime === -1) | |
| return -1; | |
| return this._endTime - this._startTime; | |
| }, | |
| get latency() | |
| { | |
| if (this._responseReceivedTime === -1 || this._startTime === -1) | |
| return -1; | |
| return this._responseReceivedTime - this._startTime; | |
| }, | |
| get receiveDuration() | |
| { | |
| if (this._endTime === -1 || this._responseReceivedTime === -1) | |
| return -1; | |
| return this._endTime - this._responseReceivedTime; | |
| }, | |
| get resourceSize() | |
| { | |
| return this._resourceSize || 0; | |
| }, | |
| set resourceSize(x) | |
| { | |
| this._resourceSize = x; | |
| }, | |
| get transferSize() | |
| { | |
| if (this.cached) | |
| return 0; | |
| if (this.statusCode === 304) | |
| return this.responseHeadersSize; | |
| if (this._transferSize !== undefined) | |
| return this._transferSize; | |
| var bodySize = Number(this.responseHeaderValue("Content-Length") || this.resourceSize); | |
| return this.responseHeadersSize + bodySize; | |
| }, | |
| increaseTransferSize: function(x) | |
| { | |
| this._transferSize = (this._transferSize || 0) + x; | |
| }, | |
| get finished() | |
| { | |
| return this._finished; | |
| }, | |
| set finished(x) | |
| { | |
| if (this._finished === x) | |
| return; | |
| this._finished = x; | |
| if (x) { | |
| this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.FinishedLoading, this); | |
| if (this._pendingContentCallbacks.length) | |
| this._innerRequestContent(); | |
| } | |
| }, | |
| get failed() | |
| { | |
| return this._failed; | |
| }, | |
| set failed(x) | |
| { | |
| this._failed = x; | |
| }, | |
| get canceled() | |
| { | |
| return this._canceled; | |
| }, | |
| set canceled(x) | |
| { | |
| this._canceled = x; | |
| }, | |
| get cached() | |
| { | |
| return this._cached; | |
| }, | |
| set cached(x) | |
| { | |
| this._cached = x; | |
| if (x) | |
| delete this._timing; | |
| }, | |
| get timing() | |
| { | |
| return this._timing; | |
| }, | |
| set timing(x) | |
| { | |
| if (x && !this._cached) { | |
| this._startTime = x.requestTime; | |
| this._responseReceivedTime = x.requestTime + x.receiveHeadersEnd / 1000.0; | |
| this._timing = x; | |
| this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.TimingChanged, this); | |
| } | |
| }, | |
| get mimeType() | |
| { | |
| return this._mimeType; | |
| }, | |
| set mimeType(x) | |
| { | |
| this._mimeType = x; | |
| }, | |
| get displayName() | |
| { | |
| return this._parsedURL.displayName; | |
| }, | |
| get folder() | |
| { | |
| var path = this._parsedURL.path; | |
| var indexOfQuery = path.indexOf("?"); | |
| if (indexOfQuery !== -1) | |
| path = path.substring(0, indexOfQuery); | |
| var lastSlashIndex = path.lastIndexOf("/"); | |
| return lastSlashIndex !== -1 ? path.substring(0, lastSlashIndex) : ""; | |
| }, | |
| get type() | |
| { | |
| return this._type; | |
| }, | |
| set type(x) | |
| { | |
| this._type = x; | |
| }, | |
| get redirectSource() | |
| { | |
| if (this.redirects && this.redirects.length > 0) | |
| return this.redirects[this.redirects.length - 1]; | |
| return this._redirectSource; | |
| }, | |
| set redirectSource(x) | |
| { | |
| this._redirectSource = x; | |
| }, | |
| get requestHeaders() | |
| { | |
| return this._requestHeaders || []; | |
| }, | |
| set requestHeaders(x) | |
| { | |
| this._requestHeaders = x; | |
| delete this._sortedRequestHeaders; | |
| delete this._requestCookies; | |
| this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.RequestHeadersChanged); | |
| }, | |
| get requestHeadersText() | |
| { | |
| if (this._requestHeadersText === undefined) { | |
| this._requestHeadersText = this.requestMethod + " " + this.url + " HTTP/1.1\r\n"; | |
| for (var i = 0; i < this.requestHeaders; ++i) | |
| this._requestHeadersText += this.requestHeaders[i].name + ": " + this.requestHeaders[i].value + "\r\n"; | |
| } | |
| return this._requestHeadersText; | |
| }, | |
| set requestHeadersText(x) | |
| { | |
| this._requestHeadersText = x; | |
| this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.RequestHeadersChanged); | |
| }, | |
| get requestHeadersSize() | |
| { | |
| return this.requestHeadersText.length; | |
| }, | |
| get sortedRequestHeaders() | |
| { | |
| if (this._sortedRequestHeaders !== undefined) | |
| return this._sortedRequestHeaders; | |
| this._sortedRequestHeaders = []; | |
| this._sortedRequestHeaders = this.requestHeaders.slice(); | |
| this._sortedRequestHeaders.sort(function(a,b) { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()) }); | |
| return this._sortedRequestHeaders; | |
| }, | |
| requestHeaderValue: function(headerName) | |
| { | |
| return this._headerValue(this.requestHeaders, headerName); | |
| }, | |
| get requestCookies() | |
| { | |
| if (!this._requestCookies) | |
| this._requestCookies = WebInspector.CookieParser.parseCookie(this.requestHeaderValue("Cookie")); | |
| return this._requestCookies; | |
| }, | |
| get requestFormData() | |
| { | |
| return this._requestFormData; | |
| }, | |
| set requestFormData(x) | |
| { | |
| this._requestFormData = x; | |
| delete this._parsedFormParameters; | |
| }, | |
| get requestHttpVersion() | |
| { | |
| var firstLine = this.requestHeadersText.split(/\r\n/)[0]; | |
| var match = firstLine.match(/(HTTP\/\d+\.\d+)$/); | |
| return match ? match[1] : undefined; | |
| }, | |
| get responseHeaders() | |
| { | |
| return this._responseHeaders || []; | |
| }, | |
| set responseHeaders(x) | |
| { | |
| this._responseHeaders = x; | |
| delete this._sortedResponseHeaders; | |
| delete this._responseCookies; | |
| this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.ResponseHeadersChanged); | |
| }, | |
| get responseHeadersText() | |
| { | |
| if (this._responseHeadersText === undefined) { | |
| this._responseHeadersText = "HTTP/1.1 " + this.statusCode + " " + this.statusText + "\r\n"; | |
| for (var i = 0; i < this.requestHeaders; ++i) | |
| this._responseHeadersText += this.responseHeaders[i].name + ": " + this.responseHeaders[i].value + "\r\n"; | |
| } | |
| return this._responseHeadersText; | |
| }, | |
| set responseHeadersText(x) | |
| { | |
| this._responseHeadersText = x; | |
| this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.ResponseHeadersChanged); | |
| }, | |
| get responseHeadersSize() | |
| { | |
| return this.responseHeadersText.length; | |
| }, | |
| get sortedResponseHeaders() | |
| { | |
| if (this._sortedResponseHeaders !== undefined) | |
| return this._sortedResponseHeaders; | |
| this._sortedResponseHeaders = []; | |
| this._sortedResponseHeaders = this.responseHeaders.slice(); | |
| this._sortedResponseHeaders.sort(function(a,b) { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()) }); | |
| return this._sortedResponseHeaders; | |
| }, | |
| responseHeaderValue: function(headerName) | |
| { | |
| return this._headerValue(this.responseHeaders, headerName); | |
| }, | |
| get responseCookies() | |
| { | |
| if (!this._responseCookies) | |
| this._responseCookies = WebInspector.CookieParser.parseSetCookie(this.responseHeaderValue("Set-Cookie")); | |
| return this._responseCookies; | |
| }, | |
| get queryParameters() | |
| { | |
| if (this._parsedQueryParameters) | |
| return this._parsedQueryParameters; | |
| var queryString = this.url.split("?", 2)[1]; | |
| if (!queryString) | |
| return null; | |
| queryString = queryString.split("#", 2)[0]; | |
| this._parsedQueryParameters = this._parseParameters(queryString); | |
| return this._parsedQueryParameters; | |
| }, | |
| get formParameters() | |
| { | |
| if (this._parsedFormParameters) | |
| return this._parsedFormParameters; | |
| if (!this.requestFormData) | |
| return null; | |
| var requestContentType = this.requestContentType(); | |
| if (!requestContentType || !requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)) | |
| return null; | |
| this._parsedFormParameters = this._parseParameters(this.requestFormData); | |
| return this._parsedFormParameters; | |
| }, | |
| get responseHttpVersion() | |
| { | |
| var match = this.responseHeadersText.match(/^(HTTP\/\d+\.\d+)/); | |
| return match ? match[1] : undefined; | |
| }, | |
| _parseParameters: function(queryString) | |
| { | |
| function parseNameValue(pair) | |
| { | |
| var parameter = {}; | |
| var splitPair = pair.split("=", 2); | |
| parameter.name = splitPair[0]; | |
| if (splitPair.length === 1) | |
| parameter.value = ""; | |
| else | |
| parameter.value = splitPair[1]; | |
| return parameter; | |
| } | |
| return queryString.split("&").map(parseNameValue); | |
| }, | |
| _headerValue: function(headers, headerName) | |
| { | |
| headerName = headerName.toLowerCase(); | |
| var values = []; | |
| for (var i = 0; i < headers.length; ++i) { | |
| if (headers[i].name.toLowerCase() === headerName) | |
| values.push(headers[i].value); | |
| } | |
| if (headerName === "set-cookie") | |
| return values.join("\n"); | |
| return values.join(", "); | |
| }, | |
| get content() | |
| { | |
| return this._content; | |
| }, | |
| get contentEncoded() | |
| { | |
| return this._contentEncoded; | |
| }, | |
| contentURL: function() | |
| { | |
| return this._url; | |
| }, | |
| contentType: function() | |
| { | |
| return this._type; | |
| }, | |
| requestContent: function(callback) | |
| { | |
| if (this.type === WebInspector.resourceTypes.WebSocket) { | |
| callback(null, false, this._mimeType); | |
| return; | |
| } | |
| if (typeof this._content !== "undefined") { | |
| callback(this.content || null, this._contentEncoded, this._mimeType); | |
| return; | |
| } | |
| this._pendingContentCallbacks.push(callback); | |
| if (this.finished) | |
| this._innerRequestContent(); | |
| }, | |
| searchInContent: function(query, caseSensitive, isRegex, callback) | |
| { | |
| callback([]); | |
| }, | |
| isHttpFamily: function() | |
| { | |
| return !!this.url.match(/^https?:/i); | |
| }, | |
| requestContentType: function() | |
| { | |
| return this.requestHeaderValue("Content-Type"); | |
| }, | |
| isPingRequest: function() | |
| { | |
| return "text/ping" === this.requestContentType(); | |
| }, | |
| hasErrorStatusCode: function() | |
| { | |
| return this.statusCode >= 400; | |
| }, | |
| populateImageSource: function(image) | |
| { | |
| function onResourceContent(content, contentEncoded, mimeType) | |
| { | |
| const maxDataUrlSize = 1024 * 1024; | |
| if (this._content == null || this._content.length > maxDataUrlSize) | |
| return this.url; | |
| image.src = "data:" + this.mimeType + (this._contentEncoded ? ";base64," : ",") + this._content; | |
| } | |
| this.requestContent(onResourceContent.bind(this)); | |
| }, | |
| _innerRequestContent: function() | |
| { | |
| if (this._contentRequested) | |
| return; | |
| this._contentRequested = true; | |
| function onResourceContent(error, content, contentEncoded) | |
| { | |
| this._content = error ? null : content; | |
| this._contentEncoded = contentEncoded; | |
| var callbacks = this._pendingContentCallbacks.slice(); | |
| for (var i = 0; i < callbacks.length; ++i) | |
| callbacks[i](this._content, this._contentEncoded, this._mimeType); | |
| this._pendingContentCallbacks.length = 0; | |
| delete this._contentRequested; | |
| } | |
| NetworkAgent.getResponseBody(this._requestId, onResourceContent.bind(this)); | |
| }, | |
| frames: function() | |
| { | |
| return this._frames; | |
| }, | |
| frame: function(position) | |
| { | |
| return this._frames[position]; | |
| }, | |
| addFrameError: function(errorMessage, time) | |
| { | |
| var errorObject = {}; | |
| errorObject.errorMessage = errorMessage; | |
| errorObject.time = time; | |
| this._pushFrame(errorObject); | |
| }, | |
| addFrame: function(response, time, sent) | |
| { | |
| response.time = time; | |
| if (sent) | |
| response.sent = true; | |
| this._pushFrame(response); | |
| }, | |
| _pushFrame: function(object) | |
| { | |
| if (this._frames.length >= 100) { | |
| this._frames.splice(0, 10); | |
| } | |
| this._frames.push(object); | |
| } | |
| } | |
| WebInspector.NetworkRequest.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.CSSStyleModel = function() | |
| { | |
| this._pendingCommandsMajorState = []; | |
| this._sourceMappings = {}; | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.UndoRedoRequested, this._undoRedoRequested, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.UndoRedoCompleted, this._undoRedoCompleted, this); | |
| this._resourceBinding = new WebInspector.CSSStyleModelResourceBinding(this); | |
| this._namedFlowCollections = {}; | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._resetNamedFlowCollections, this); | |
| InspectorBackend.registerCSSDispatcher(new WebInspector.CSSDispatcher(this)); | |
| CSSAgent.enable(); | |
| } | |
| WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray) | |
| { | |
| var result = []; | |
| for (var i = 0; i < ruleArray.length; ++i) | |
| result.push(WebInspector.CSSRule.parsePayload(ruleArray[i])); | |
| return result; | |
| } | |
| WebInspector.CSSStyleModel.Events = { | |
| StyleSheetChanged: "StyleSheetChanged", | |
| MediaQueryResultChanged: "MediaQueryResultChanged", | |
| NamedFlowCreated: "NamedFlowCreated", | |
| NamedFlowRemoved: "NamedFlowRemoved", | |
| RegionLayoutUpdated: "RegionLayoutUpdated" | |
| } | |
| WebInspector.CSSStyleModel.prototype = { | |
| getMatchedStylesAsync: function(nodeId, needPseudo, needInherited, userCallback) | |
| { | |
| function callback(userCallback, error, matchedPayload, pseudoPayload, inheritedPayload) | |
| { | |
| if (error) { | |
| if (userCallback) | |
| userCallback(null); | |
| return; | |
| } | |
| var result = {}; | |
| if (matchedPayload) | |
| result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(matchedPayload); | |
| if (pseudoPayload) { | |
| result.pseudoElements = []; | |
| for (var i = 0; i < pseudoPayload.length; ++i) { | |
| var entryPayload = pseudoPayload[i]; | |
| result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) }); | |
| } | |
| } | |
| if (inheritedPayload) { | |
| result.inherited = []; | |
| for (var i = 0; i < inheritedPayload.length; ++i) { | |
| var entryPayload = inheritedPayload[i]; | |
| var entry = {}; | |
| if (entryPayload.inlineStyle) | |
| entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle); | |
| if (entryPayload.matchedCSSRules) | |
| entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules); | |
| result.inherited.push(entry); | |
| } | |
| } | |
| if (userCallback) | |
| userCallback(result); | |
| } | |
| CSSAgent.getMatchedStylesForNode(nodeId, needPseudo, needInherited, callback.bind(null, userCallback)); | |
| }, | |
| getComputedStyleAsync: function(nodeId, userCallback) | |
| { | |
| function callback(userCallback, error, computedPayload) | |
| { | |
| if (error || !computedPayload) | |
| userCallback(null); | |
| else | |
| userCallback(WebInspector.CSSStyleDeclaration.parseComputedStylePayload(computedPayload)); | |
| } | |
| CSSAgent.getComputedStyleForNode(nodeId, callback.bind(null, userCallback)); | |
| }, | |
| getInlineStylesAsync: function(nodeId, userCallback) | |
| { | |
| function callback(userCallback, error, inlinePayload, attributesStylePayload) | |
| { | |
| if (error || !inlinePayload) | |
| userCallback(null, null); | |
| else | |
| userCallback(WebInspector.CSSStyleDeclaration.parsePayload(inlinePayload), attributesStylePayload ? WebInspector.CSSStyleDeclaration.parsePayload(attributesStylePayload) : null); | |
| } | |
| CSSAgent.getInlineStylesForNode(nodeId, callback.bind(null, userCallback)); | |
| }, | |
| forcePseudoState: function(nodeId, forcedPseudoClasses, userCallback) | |
| { | |
| CSSAgent.forcePseudoState(nodeId, forcedPseudoClasses || [], userCallback); | |
| }, | |
| getNamedFlowCollectionAsync: function(documentNodeId, userCallback) | |
| { | |
| var namedFlowCollection = this._namedFlowCollections[documentNodeId]; | |
| if (namedFlowCollection) { | |
| userCallback(namedFlowCollection); | |
| return; | |
| } | |
| function callback(userCallback, error, namedFlowPayload) | |
| { | |
| if (error || !namedFlowPayload) | |
| userCallback(null); | |
| else { | |
| var namedFlowCollection = new WebInspector.NamedFlowCollection(namedFlowPayload); | |
| this._namedFlowCollections[documentNodeId] = namedFlowCollection; | |
| userCallback(namedFlowCollection); | |
| } | |
| } | |
| CSSAgent.getNamedFlowCollection(documentNodeId, callback.bind(this, userCallback)); | |
| }, | |
| getFlowByNameAsync: function(documentNodeId, flowName, userCallback) | |
| { | |
| var namedFlowCollection = this._namedFlowCollections[documentNodeId]; | |
| if (namedFlowCollection) { | |
| userCallback(namedFlowCollection.flowByName(flowName)); | |
| return; | |
| } | |
| function callback(userCallback, namedFlowCollection) | |
| { | |
| if (!namedFlowCollection) | |
| userCallback(null); | |
| else | |
| userCallback(namedFlowCollection.flowByName(flowName)); | |
| } | |
| this.getNamedFlowCollectionAsync(documentNodeId, callback.bind(this, userCallback)); | |
| }, | |
| setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback) | |
| { | |
| function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds) | |
| { | |
| if (!selectedNodeIds) | |
| return; | |
| var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0); | |
| var rule = WebInspector.CSSRule.parsePayload(rulePayload); | |
| successCallback(rule, doesAffectSelectedNode); | |
| } | |
| function callback(nodeId, successCallback, failureCallback, newSelector, error, rulePayload) | |
| { | |
| this._pendingCommandsMajorState.pop(); | |
| if (error) | |
| failureCallback(); | |
| else { | |
| WebInspector.domAgent.markUndoableState(); | |
| var ownerDocumentId = this._ownerDocumentId(nodeId); | |
| if (ownerDocumentId) | |
| WebInspector.domAgent.querySelectorAll(ownerDocumentId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); | |
| else | |
| failureCallback(); | |
| } | |
| } | |
| this._pendingCommandsMajorState.push(true); | |
| CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback, newSelector)); | |
| }, | |
| addRule: function(nodeId, selector, successCallback, failureCallback) | |
| { | |
| function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds) | |
| { | |
| if (!selectedNodeIds) | |
| return; | |
| var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0); | |
| var rule = WebInspector.CSSRule.parsePayload(rulePayload); | |
| successCallback(rule, doesAffectSelectedNode); | |
| } | |
| function callback(successCallback, failureCallback, selector, error, rulePayload) | |
| { | |
| this._pendingCommandsMajorState.pop(); | |
| if (error) { | |
| failureCallback(); | |
| } else { | |
| WebInspector.domAgent.markUndoableState(); | |
| var ownerDocumentId = this._ownerDocumentId(nodeId); | |
| if (ownerDocumentId) | |
| WebInspector.domAgent.querySelectorAll(ownerDocumentId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); | |
| else | |
| failureCallback(); | |
| } | |
| } | |
| this._pendingCommandsMajorState.push(true); | |
| CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector)); | |
| }, | |
| mediaQueryResultChanged: function() | |
| { | |
| this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged); | |
| }, | |
| _ownerDocumentId: function(nodeId) | |
| { | |
| var node = WebInspector.domAgent.nodeForId(nodeId); | |
| if (!node) | |
| return null; | |
| return node.ownerDocument ? node.ownerDocument.id : null; | |
| }, | |
| _fireStyleSheetChanged: function(styleSheetId) | |
| { | |
| if (!this._pendingCommandsMajorState.length) | |
| return; | |
| var majorChange = this._pendingCommandsMajorState[this._pendingCommandsMajorState.length - 1]; | |
| if (!majorChange || !styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged)) | |
| return; | |
| this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, majorChange: majorChange }); | |
| }, | |
| _namedFlowCreated: function(namedFlowPayload) | |
| { | |
| var namedFlow = WebInspector.NamedFlow.parsePayload(namedFlowPayload); | |
| var namedFlowCollection = this._namedFlowCollections[namedFlow.documentNodeId]; | |
| if (!namedFlowCollection) | |
| return; | |
| namedFlowCollection._appendNamedFlow(namedFlow); | |
| this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.NamedFlowCreated, namedFlow); | |
| }, | |
| _namedFlowRemoved: function(documentNodeId, flowName) | |
| { | |
| var namedFlowCollection = this._namedFlowCollections[documentNodeId]; | |
| if (!namedFlowCollection) | |
| return; | |
| namedFlowCollection._removeNamedFlow(flowName); | |
| this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, { documentNodeId: documentNodeId, flowName: flowName }); | |
| }, | |
| _regionLayoutUpdated: function(namedFlowPayload) | |
| { | |
| var namedFlow = WebInspector.NamedFlow.parsePayload(namedFlowPayload); | |
| var namedFlowCollection = this._namedFlowCollections[namedFlow.documentNodeId]; | |
| if (!namedFlowCollection) | |
| return; | |
| namedFlowCollection._appendNamedFlow(namedFlow); | |
| this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, namedFlow); | |
| }, | |
| setStyleSheetText: function(styleSheetId, newText, majorChange, userCallback) | |
| { | |
| function callback(error) | |
| { | |
| this._pendingCommandsMajorState.pop(); | |
| if (!error && majorChange) | |
| WebInspector.domAgent.markUndoableState(); | |
| if (!error && userCallback) | |
| userCallback(error); | |
| } | |
| this._pendingCommandsMajorState.push(majorChange); | |
| CSSAgent.setStyleSheetText(styleSheetId, newText, callback.bind(this)); | |
| }, | |
| _undoRedoRequested: function() | |
| { | |
| this._pendingCommandsMajorState.push(true); | |
| }, | |
| _undoRedoCompleted: function() | |
| { | |
| this._pendingCommandsMajorState.pop(); | |
| }, | |
| getViaInspectorResourceForRule: function(rule, callback) | |
| { | |
| if (!rule.id) { | |
| callback(null); | |
| return; | |
| } | |
| this._resourceBinding._requestViaInspectorResource(rule.id.styleSheetId, callback); | |
| }, | |
| resourceBinding: function() | |
| { | |
| return this._resourceBinding; | |
| }, | |
| setSourceMapping: function(url, sourceMapping) | |
| { | |
| this._sourceMappings[url] = sourceMapping; | |
| }, | |
| resetSourceMappings: function() | |
| { | |
| this._sourceMappings = {}; | |
| }, | |
| _resetNamedFlowCollections: function() | |
| { | |
| this._namedFlowCollections = {}; | |
| }, | |
| _rawLocationToUILocation: function(rawLocation) | |
| { | |
| var sourceMapping = this._sourceMappings[rawLocation.url]; | |
| return sourceMapping ? sourceMapping.rawLocationToUILocation(rawLocation) : null; | |
| } | |
| } | |
| WebInspector.CSSStyleModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.CSSLocation = function(url, lineNumber) | |
| { | |
| this.url = url; | |
| this.lineNumber = lineNumber; | |
| } | |
| WebInspector.CSSStyleDeclaration = function(payload) | |
| { | |
| this.id = payload.styleId; | |
| this.width = payload.width; | |
| this.height = payload.height; | |
| this.range = payload.range; | |
| this._shorthandValues = WebInspector.CSSStyleDeclaration.buildShorthandValueMap(payload.shorthandEntries); | |
| this._livePropertyMap = {}; | |
| this._allProperties = []; | |
| this.__disabledProperties = {}; | |
| var payloadPropertyCount = payload.cssProperties.length; | |
| var propertyIndex = 0; | |
| for (var i = 0; i < payloadPropertyCount; ++i) { | |
| var property = WebInspector.CSSProperty.parsePayload(this, i, payload.cssProperties[i]); | |
| this._allProperties.push(property); | |
| if (property.disabled) | |
| this.__disabledProperties[i] = property; | |
| if (!property.active && !property.styleBased) | |
| continue; | |
| var name = property.name; | |
| this[propertyIndex] = name; | |
| this._livePropertyMap[name] = property; | |
| ++propertyIndex; | |
| } | |
| this.length = propertyIndex; | |
| if ("cssText" in payload) | |
| this.cssText = payload.cssText; | |
| } | |
| WebInspector.CSSStyleDeclaration.buildShorthandValueMap = function(shorthandEntries) | |
| { | |
| var result = {}; | |
| for (var i = 0; i < shorthandEntries.length; ++i) | |
| result[shorthandEntries[i].name] = shorthandEntries[i].value; | |
| return result; | |
| } | |
| WebInspector.CSSStyleDeclaration.parsePayload = function(payload) | |
| { | |
| return new WebInspector.CSSStyleDeclaration(payload); | |
| } | |
| WebInspector.CSSStyleDeclaration.parseComputedStylePayload = function(payload) | |
| { | |
| var newPayload = { cssProperties: [], shorthandEntries: [], width: "", height: "" }; | |
| if (payload) | |
| newPayload.cssProperties = payload; | |
| return new WebInspector.CSSStyleDeclaration(newPayload); | |
| } | |
| WebInspector.CSSStyleDeclaration.prototype = { | |
| get allProperties() | |
| { | |
| return this._allProperties; | |
| }, | |
| getLiveProperty: function(name) | |
| { | |
| return this._livePropertyMap[name]; | |
| }, | |
| getPropertyValue: function(name) | |
| { | |
| var property = this._livePropertyMap[name]; | |
| return property ? property.value : ""; | |
| }, | |
| getPropertyPriority: function(name) | |
| { | |
| var property = this._livePropertyMap[name]; | |
| return property ? property.priority : ""; | |
| }, | |
| isPropertyImplicit: function(name) | |
| { | |
| var property = this._livePropertyMap[name]; | |
| return property ? property.implicit : ""; | |
| }, | |
| longhandProperties: function(name) | |
| { | |
| var longhands = WebInspector.CSSCompletions.cssPropertiesMetainfo.longhands(name); | |
| var result = []; | |
| for (var i = 0; longhands && i < longhands.length; ++i) { | |
| var property = this._livePropertyMap[longhands[i]]; | |
| if (property) | |
| result.push(property); | |
| } | |
| return result; | |
| }, | |
| shorthandValue: function(shorthandProperty) | |
| { | |
| return this._shorthandValues[shorthandProperty]; | |
| }, | |
| propertyAt: function(index) | |
| { | |
| return (index < this.allProperties.length) ? this.allProperties[index] : null; | |
| }, | |
| pastLastSourcePropertyIndex: function() | |
| { | |
| for (var i = this.allProperties.length - 1; i >= 0; --i) { | |
| var property = this.allProperties[i]; | |
| if (property.active || property.disabled) | |
| return i + 1; | |
| } | |
| return 0; | |
| }, | |
| newBlankProperty: function(index) | |
| { | |
| index = (typeof index === "undefined") ? this.pastLastSourcePropertyIndex() : index; | |
| return new WebInspector.CSSProperty(this, index, "", "", "", "active", true, false, ""); | |
| }, | |
| insertPropertyAt: function(index, name, value, userCallback) | |
| { | |
| function callback(userCallback, error, payload) | |
| { | |
| WebInspector.cssModel._pendingCommandsMajorState.pop(); | |
| if (!userCallback) | |
| return; | |
| if (error) { | |
| console.error(error); | |
| userCallback(null); | |
| } else { | |
| userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload)); | |
| } | |
| } | |
| if (!this.id) | |
| throw "No style id"; | |
| WebInspector.cssModel._pendingCommandsMajorState.push(true); | |
| CSSAgent.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(this, userCallback)); | |
| }, | |
| appendProperty: function(name, value, userCallback) | |
| { | |
| this.insertPropertyAt(this.allProperties.length, name, value, userCallback); | |
| } | |
| } | |
| WebInspector.CSSRule = function(payload) | |
| { | |
| this.id = payload.ruleId; | |
| this.selectorText = payload.selectorText; | |
| this.sourceLine = payload.sourceLine; | |
| this.sourceURL = payload.sourceURL; | |
| if (payload.sourceURL) | |
| this._rawLocation = new WebInspector.CSSLocation(payload.sourceURL, payload.sourceLine); | |
| this.origin = payload.origin; | |
| this.style = WebInspector.CSSStyleDeclaration.parsePayload(payload.style); | |
| this.style.parentRule = this; | |
| this.selectorRange = payload.selectorRange; | |
| if (payload.media) | |
| this.media = WebInspector.CSSMedia.parseMediaArrayPayload(payload.media); | |
| } | |
| WebInspector.CSSRule.parsePayload = function(payload) | |
| { | |
| return new WebInspector.CSSRule(payload); | |
| } | |
| WebInspector.CSSRule.prototype = { | |
| get isUserAgent() | |
| { | |
| return this.origin === "user-agent"; | |
| }, | |
| get isUser() | |
| { | |
| return this.origin === "user"; | |
| }, | |
| get isViaInspector() | |
| { | |
| return this.origin === "inspector"; | |
| }, | |
| get isRegular() | |
| { | |
| return this.origin === "regular"; | |
| }, | |
| uiLocation: function() | |
| { | |
| if (!this._rawLocation) | |
| return null; | |
| return WebInspector.cssModel._rawLocationToUILocation(this._rawLocation); | |
| } | |
| } | |
| WebInspector.CSSProperty = function(ownerStyle, index, name, value, priority, status, parsedOk, implicit, text) | |
| { | |
| this.ownerStyle = ownerStyle; | |
| this.index = index; | |
| this.name = name; | |
| this.value = value; | |
| this.priority = priority; | |
| this.status = status; | |
| this.parsedOk = parsedOk; | |
| this.implicit = implicit; | |
| this.text = text; | |
| } | |
| WebInspector.CSSProperty.parsePayload = function(ownerStyle, index, payload) | |
| { | |
| var result = new WebInspector.CSSProperty( | |
| ownerStyle, index, payload.name, payload.value, payload.priority || "", payload.status || "style", ("parsedOk" in payload) ? !!payload.parsedOk : true, !!payload.implicit, payload.text); | |
| return result; | |
| } | |
| WebInspector.CSSProperty.prototype = { | |
| get propertyText() | |
| { | |
| if (this.text !== undefined) | |
| return this.text; | |
| if (this.name === "") | |
| return ""; | |
| return this.name + ": " + this.value + (this.priority ? " !" + this.priority : "") + ";"; | |
| }, | |
| get isLive() | |
| { | |
| return this.active || this.styleBased; | |
| }, | |
| get active() | |
| { | |
| return this.status === "active"; | |
| }, | |
| get styleBased() | |
| { | |
| return this.status === "style"; | |
| }, | |
| get inactive() | |
| { | |
| return this.status === "inactive"; | |
| }, | |
| get disabled() | |
| { | |
| return this.status === "disabled"; | |
| }, | |
| setText: function(propertyText, majorChange, overwrite, userCallback) | |
| { | |
| function enabledCallback(style) | |
| { | |
| if (userCallback) | |
| userCallback(style); | |
| } | |
| function callback(error, stylePayload) | |
| { | |
| WebInspector.cssModel._pendingCommandsMajorState.pop(); | |
| if (!error) { | |
| if (majorChange) | |
| WebInspector.domAgent.markUndoableState(); | |
| this.text = propertyText; | |
| var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload); | |
| var newProperty = style.allProperties[this.index]; | |
| if (newProperty && this.disabled && !propertyText.match(/^\s*$/)) { | |
| newProperty.setDisabled(false, enabledCallback); | |
| return; | |
| } | |
| if (userCallback) | |
| userCallback(style); | |
| } else { | |
| if (userCallback) | |
| userCallback(null); | |
| } | |
| } | |
| if (!this.ownerStyle) | |
| throw "No ownerStyle for property"; | |
| if (!this.ownerStyle.id) | |
| throw "No owner style id"; | |
| WebInspector.cssModel._pendingCommandsMajorState.push(majorChange); | |
| CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, overwrite, callback.bind(this)); | |
| }, | |
| setValue: function(newValue, majorChange, overwrite, userCallback) | |
| { | |
| var text = this.name + ": " + newValue + (this.priority ? " !" + this.priority : "") + ";" | |
| this.setText(text, majorChange, overwrite, userCallback); | |
| }, | |
| setDisabled: function(disabled, userCallback) | |
| { | |
| if (!this.ownerStyle && userCallback) | |
| userCallback(null); | |
| if (disabled === this.disabled && userCallback) | |
| userCallback(this.ownerStyle); | |
| function callback(error, stylePayload) | |
| { | |
| WebInspector.cssModel._pendingCommandsMajorState.pop(); | |
| if (error) { | |
| if (userCallback) | |
| userCallback(null); | |
| return; | |
| } | |
| WebInspector.domAgent.markUndoableState(); | |
| if (userCallback) { | |
| var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload); | |
| userCallback(style); | |
| } | |
| } | |
| if (!this.ownerStyle.id) | |
| throw "No owner style id"; | |
| WebInspector.cssModel._pendingCommandsMajorState.push(false); | |
| CSSAgent.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this)); | |
| } | |
| } | |
| WebInspector.CSSMedia = function(payload) | |
| { | |
| this.text = payload.text; | |
| this.source = payload.source; | |
| this.sourceURL = payload.sourceURL || ""; | |
| this.sourceLine = typeof payload.sourceLine === "undefined" || this.source === "linkedSheet" ? -1 : payload.sourceLine; | |
| } | |
| WebInspector.CSSMedia.Source = { | |
| LINKED_SHEET: "linkedSheet", | |
| INLINE_SHEET: "inlineSheet", | |
| MEDIA_RULE: "mediaRule", | |
| IMPORT_RULE: "importRule" | |
| }; | |
| WebInspector.CSSMedia.parsePayload = function(payload) | |
| { | |
| return new WebInspector.CSSMedia(payload); | |
| } | |
| WebInspector.CSSMedia.parseMediaArrayPayload = function(payload) | |
| { | |
| var result = []; | |
| for (var i = 0; i < payload.length; ++i) | |
| result.push(WebInspector.CSSMedia.parsePayload(payload[i])); | |
| return result; | |
| } | |
| WebInspector.CSSStyleSheet = function(payload) | |
| { | |
| this.id = payload.styleSheetId; | |
| this.rules = []; | |
| this.styles = {}; | |
| for (var i = 0; i < payload.rules.length; ++i) { | |
| var rule = WebInspector.CSSRule.parsePayload(payload.rules[i]); | |
| this.rules.push(rule); | |
| if (rule.style) | |
| this.styles[rule.style.id] = rule.style; | |
| } | |
| if ("text" in payload) | |
| this._text = payload.text; | |
| } | |
| WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback) | |
| { | |
| function callback(error, styleSheetPayload) | |
| { | |
| if (error) | |
| userCallback(null); | |
| else | |
| userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload)); | |
| } | |
| CSSAgent.getStyleSheet(styleSheetId, callback.bind(this)); | |
| } | |
| WebInspector.CSSStyleSheet.prototype = { | |
| getText: function() | |
| { | |
| return this._text; | |
| }, | |
| setText: function(newText, majorChange, userCallback) | |
| { | |
| function callback(error) | |
| { | |
| if (!error) | |
| WebInspector.domAgent.markUndoableState(); | |
| WebInspector.cssModel._pendingCommandsMajorState.pop(); | |
| if (userCallback) | |
| userCallback(error); | |
| } | |
| WebInspector.cssModel._pendingCommandsMajorState.push(majorChange); | |
| CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this)); | |
| } | |
| } | |
| WebInspector.CSSStyleModelResourceBinding = function(cssModel) | |
| { | |
| this._cssModel = cssModel; | |
| this._frameAndURLToStyleSheetId = {}; | |
| this._styleSheetIdToHeader = {}; | |
| this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this); | |
| } | |
| WebInspector.CSSStyleModelResourceBinding.prototype = { | |
| setStyleContent: function(styleSource, content, majorChange, userCallback) | |
| { | |
| var resource = styleSource.resource(); | |
| if (this._styleSheetIdForResource(resource)) { | |
| this._innerSetContent(resource, content, majorChange, userCallback, null); | |
| return; | |
| } | |
| this._loadStyleSheetHeaders(this._innerSetContent.bind(this, resource, content, majorChange, userCallback)); | |
| }, | |
| _styleSheetIdForResource: function(resource) | |
| { | |
| return this._frameAndURLToStyleSheetId[resource.frameId + ":" + resource.url]; | |
| }, | |
| _inspectedURLChanged: function(event) | |
| { | |
| this._frameAndURLToStyleSheetId = {}; | |
| this._styleSheetIdToHeader = {}; | |
| }, | |
| _innerSetContent: function(resource, content, majorChange, userCallback, error) | |
| { | |
| if (error) { | |
| userCallback(error); | |
| return; | |
| } | |
| var styleSheetId = this._styleSheetIdForResource(resource); | |
| if (!styleSheetId) { | |
| userCallback("No stylesheet found: " + resource.frameId + ":" + resource.url); | |
| return; | |
| } | |
| this._isSettingContent = true; | |
| function callbackWrapper(error) | |
| { | |
| userCallback(error); | |
| delete this._isSettingContent; | |
| } | |
| this._cssModel.setStyleSheetText(styleSheetId, content, majorChange, callbackWrapper.bind(this)); | |
| }, | |
| _loadStyleSheetHeaders: function(callback) | |
| { | |
| function didGetAllStyleSheets(error, infos) | |
| { | |
| if (error) { | |
| callback(error); | |
| return; | |
| } | |
| for (var i = 0; i < infos.length; ++i) { | |
| var info = infos[i]; | |
| if (info.origin === "inspector") { | |
| this._getOrCreateInspectorResource(info); | |
| continue; | |
| } | |
| this._frameAndURLToStyleSheetId[info.frameId + ":" + info.sourceURL] = info.styleSheetId; | |
| this._styleSheetIdToHeader[info.styleSheetId] = info; | |
| } | |
| callback(null); | |
| } | |
| CSSAgent.getAllStyleSheets(didGetAllStyleSheets.bind(this)); | |
| }, | |
| _styleSheetChanged: function(event) | |
| { | |
| if (this._isSettingContent) | |
| return; | |
| if (!event.data.majorChange) | |
| return; | |
| function callback(error, content) | |
| { | |
| if (!error) | |
| this._innerStyleSheetChanged(event.data.styleSheetId, content); | |
| } | |
| CSSAgent.getStyleSheetText(event.data.styleSheetId, callback.bind(this)); | |
| }, | |
| _innerStyleSheetChanged: function(styleSheetId, content) | |
| { | |
| function setContent() | |
| { | |
| var header = this._styleSheetIdToHeader[styleSheetId]; | |
| if (!header) | |
| return; | |
| var frame = WebInspector.resourceTreeModel.frameForId(header.frameId); | |
| if (!frame) | |
| return; | |
| var styleSheetURL = header.origin === "inspector" ? this._viaInspectorResourceURL(header.sourceURL) : header.sourceURL; | |
| var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(styleSheetURL); | |
| if (!uiSourceCode) | |
| return; | |
| if (uiSourceCode.contentType() === WebInspector.resourceTypes.Stylesheet) | |
| uiSourceCode.addRevision(content); | |
| } | |
| if (!this._styleSheetIdToHeader[styleSheetId]) { | |
| this._loadStyleSheetHeaders(setContent.bind(this)); | |
| return; | |
| } | |
| setContent.call(this); | |
| }, | |
| _requestViaInspectorResource: function(styleSheetId, callback) | |
| { | |
| var header = this._styleSheetIdToHeader[styleSheetId]; | |
| if (header) { | |
| callback(this._getOrCreateInspectorResource(header)); | |
| return; | |
| } | |
| function headersLoaded() | |
| { | |
| var header = this._styleSheetIdToHeader[styleSheetId]; | |
| if (header) | |
| callback(this._getOrCreateInspectorResource(header)); | |
| else | |
| callback(null); | |
| } | |
| this._loadStyleSheetHeaders(headersLoaded.bind(this)); | |
| }, | |
| _getOrCreateInspectorResource: function(header) | |
| { | |
| var frame = WebInspector.resourceTreeModel.frameForId(header.frameId); | |
| if (!frame) | |
| return null; | |
| var viaInspectorURL = this._viaInspectorResourceURL(header.sourceURL); | |
| var inspectorResource = frame.resourceForURL(viaInspectorURL); | |
| if (inspectorResource) | |
| return inspectorResource; | |
| var resource = frame.resourceForURL(header.sourceURL); | |
| if (!resource) | |
| return null; | |
| this._frameAndURLToStyleSheetId[header.frameId + ":" + viaInspectorURL] = header.styleSheetId; | |
| this._styleSheetIdToHeader[header.styleSheetId] = header; | |
| inspectorResource = new WebInspector.Resource(null, viaInspectorURL, resource.documentURL, resource.frameId, resource.loaderId, WebInspector.resourceTypes.Stylesheet, "text/css", true); | |
| function overrideRequestContent(callback) | |
| { | |
| function callbackWrapper(error, content) | |
| { | |
| callback(error ? "" : content, false, "text/css"); | |
| } | |
| CSSAgent.getStyleSheetText(header.styleSheetId, callbackWrapper); | |
| } | |
| inspectorResource.requestContent = overrideRequestContent; | |
| frame.addResource(inspectorResource); | |
| return inspectorResource; | |
| }, | |
| _viaInspectorResourceURL: function(documentURL) | |
| { | |
| var parsedURL = new WebInspector.ParsedURL(documentURL); | |
| var fakeURL = "inspector://" + parsedURL.host + parsedURL.folderPathComponents; | |
| if (!fakeURL.endsWith("/")) | |
| fakeURL += "/"; | |
| fakeURL += "inspector-stylesheet"; | |
| return fakeURL; | |
| } | |
| } | |
| WebInspector.CSSDispatcher = function(cssModel) | |
| { | |
| this._cssModel = cssModel; | |
| } | |
| WebInspector.CSSDispatcher.prototype = { | |
| mediaQueryResultChanged: function() | |
| { | |
| this._cssModel.mediaQueryResultChanged(); | |
| }, | |
| styleSheetChanged: function(styleSheetId) | |
| { | |
| this._cssModel._fireStyleSheetChanged(styleSheetId); | |
| }, | |
| namedFlowCreated: function(namedFlowPayload) | |
| { | |
| this._cssModel._namedFlowCreated(namedFlowPayload); | |
| }, | |
| namedFlowRemoved: function(documentNodeId, flowName) | |
| { | |
| this._cssModel._namedFlowRemoved(documentNodeId, flowName); | |
| }, | |
| regionLayoutUpdated: function(namedFlowPayload) | |
| { | |
| this._cssModel._regionLayoutUpdated(namedFlowPayload); | |
| } | |
| } | |
| WebInspector.NamedFlow = function(payload) | |
| { | |
| this.documentNodeId = payload.documentNodeId; | |
| this.name = payload.name; | |
| this.overset = payload.overset; | |
| this.content = payload.content; | |
| this.regions = payload.regions; | |
| } | |
| WebInspector.NamedFlow.parsePayload = function(payload) | |
| { | |
| return new WebInspector.NamedFlow(payload); | |
| } | |
| WebInspector.NamedFlowCollection = function(payload) | |
| { | |
| this.namedFlowMap = {}; | |
| for (var i = 0; i < payload.length; ++i) { | |
| var namedFlow = WebInspector.NamedFlow.parsePayload(payload[i]); | |
| this.namedFlowMap[namedFlow.name] = namedFlow; | |
| } | |
| } | |
| WebInspector.NamedFlowCollection.prototype = { | |
| _appendNamedFlow: function(namedFlow) | |
| { | |
| this.namedFlowMap[namedFlow.name] = namedFlow; | |
| }, | |
| _removeNamedFlow: function(flowName) | |
| { | |
| delete this.namedFlowMap[flowName]; | |
| }, | |
| flowByName: function(flowName) | |
| { | |
| var namedFlow = this.namedFlowMap[flowName]; | |
| if (!namedFlow) | |
| return null; | |
| return namedFlow; | |
| } | |
| } | |
| WebInspector.cssModel = null; | |
| WebInspector.NetworkManager = function() | |
| { | |
| WebInspector.Object.call(this); | |
| this._dispatcher = new WebInspector.NetworkDispatcher(this); | |
| if (WebInspector.settings.cacheDisabled.get()) | |
| NetworkAgent.setCacheDisabled(true); | |
| NetworkAgent.enable(); | |
| WebInspector.settings.cacheDisabled.addChangeListener(this._cacheDisabledSettingChanged, this); | |
| if (WebInspector.settings.userAgent.get()) | |
| this._userAgentSettingChanged(); | |
| WebInspector.settings.userAgent.addChangeListener(this._userAgentSettingChanged, this); | |
| } | |
| WebInspector.NetworkManager.EventTypes = { | |
| RequestStarted: "RequestStarted", | |
| RequestUpdated: "RequestUpdated", | |
| RequestFinished: "RequestFinished", | |
| RequestUpdateDropped: "RequestUpdateDropped" | |
| } | |
| WebInspector.NetworkManager._MIMETypes = { | |
| "text/html": {"document": true}, | |
| "text/xml": {"document": true}, | |
| "text/plain": {"document": true}, | |
| "application/xhtml+xml": {"document": true}, | |
| "text/css": {"stylesheet": true}, | |
| "text/xsl": {"stylesheet": true}, | |
| "image/jpeg": {"image": true}, | |
| "image/png": {"image": true}, | |
| "image/gif": {"image": true}, | |
| "image/bmp": {"image": true}, | |
| "image/svg+xml": {"image": true}, | |
| "image/vnd.microsoft.icon": {"image": true}, | |
| "image/webp": {"image": true}, | |
| "image/x-icon": {"image": true}, | |
| "image/x-xbitmap": {"image": true}, | |
| "font/ttf": {"font": true}, | |
| "font/opentype": {"font": true}, | |
| "font/woff": {"font": true}, | |
| "application/x-font-type1": {"font": true}, | |
| "application/x-font-ttf": {"font": true}, | |
| "application/x-font-woff": {"font": true}, | |
| "application/x-truetype-font": {"font": true}, | |
| "text/javascript": {"script": true}, | |
| "text/ecmascript": {"script": true}, | |
| "application/javascript": {"script": true}, | |
| "application/ecmascript": {"script": true}, | |
| "application/x-javascript": {"script": true}, | |
| "application/json": {"script": true}, | |
| "text/javascript1.1": {"script": true}, | |
| "text/javascript1.2": {"script": true}, | |
| "text/javascript1.3": {"script": true}, | |
| "text/jscript": {"script": true}, | |
| "text/livescript": {"script": true}, | |
| } | |
| WebInspector.NetworkManager.prototype = { | |
| inflightRequestForURL: function(url) | |
| { | |
| return this._dispatcher._inflightRequestsByURL[url]; | |
| }, | |
| _cacheDisabledSettingChanged: function(event) | |
| { | |
| var enabled = event.data; | |
| NetworkAgent.setCacheDisabled(enabled); | |
| }, | |
| _userAgentSettingChanged: function() | |
| { | |
| NetworkAgent.setUserAgentOverride(WebInspector.settings.userAgent.get()); | |
| } | |
| } | |
| WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.NetworkDispatcher = function(manager) | |
| { | |
| this._manager = manager; | |
| this._inflightRequestsById = {}; | |
| this._inflightRequestsByURL = {}; | |
| InspectorBackend.registerNetworkDispatcher(this); | |
| } | |
| WebInspector.NetworkDispatcher.prototype = { | |
| _headersMapToHeadersArray: function(headersMap) | |
| { | |
| var result = []; | |
| for (var name in headersMap) { | |
| var values = headersMap[name].split("\n"); | |
| for (var i = 0; i < values.length; ++i) | |
| result.push({ name: name, value: values[i] }); | |
| } | |
| return result; | |
| }, | |
| _updateNetworkRequestWithRequest: function(networkRequest, request) | |
| { | |
| networkRequest.requestMethod = request.method; | |
| networkRequest.requestHeaders = this._headersMapToHeadersArray(request.headers); | |
| networkRequest.requestFormData = request.postData; | |
| }, | |
| _updateNetworkRequestWithResponse: function(networkRequest, response) | |
| { | |
| if (!response) | |
| return; | |
| if (response.url && networkRequest.url !== response.url) | |
| networkRequest.url = response.url; | |
| networkRequest.mimeType = response.mimeType; | |
| networkRequest.statusCode = response.status; | |
| networkRequest.statusText = response.statusText; | |
| networkRequest.responseHeaders = this._headersMapToHeadersArray(response.headers); | |
| if (response.headersText) | |
| networkRequest.responseHeadersText = response.headersText; | |
| if (response.requestHeaders) | |
| networkRequest.requestHeaders = this._headersMapToHeadersArray(response.requestHeaders); | |
| if (response.requestHeadersText) | |
| networkRequest.requestHeadersText = response.requestHeadersText; | |
| networkRequest.connectionReused = response.connectionReused; | |
| networkRequest.connectionId = response.connectionId; | |
| if (response.fromDiskCache) | |
| networkRequest.cached = true; | |
| else | |
| networkRequest.timing = response.timing; | |
| if (!this._mimeTypeIsConsistentWithType(networkRequest)) { | |
| WebInspector.console.addMessage(WebInspector.ConsoleMessage.create(WebInspector.ConsoleMessage.MessageSource.Network, | |
| WebInspector.ConsoleMessage.MessageLevel.Warning, | |
| WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s: \"%s\".", networkRequest.type.title(), networkRequest.mimeType, networkRequest.url), | |
| WebInspector.ConsoleMessage.MessageType.Log, | |
| "", | |
| 0, | |
| 1, | |
| [], | |
| null, | |
| networkRequest.requestId)); | |
| } | |
| }, | |
| _mimeTypeIsConsistentWithType: function(networkRequest) | |
| { | |
| if (networkRequest.hasErrorStatusCode() || networkRequest.statusCode === 304 || networkRequest.statusCode === 204) | |
| return true; | |
| if (typeof networkRequest.type === "undefined" | |
| || networkRequest.type === WebInspector.resourceTypes.Other | |
| || networkRequest.type === WebInspector.resourceTypes.XHR | |
| || networkRequest.type === WebInspector.resourceTypes.WebSocket) | |
| return true; | |
| if (!networkRequest.mimeType) | |
| return true; | |
| if (networkRequest.mimeType in WebInspector.NetworkManager._MIMETypes) | |
| return networkRequest.type.name() in WebInspector.NetworkManager._MIMETypes[networkRequest.mimeType]; | |
| return false; | |
| }, | |
| _updateNetworkRequestWithCachedResource: function(networkRequest, cachedResource) | |
| { | |
| networkRequest.type = WebInspector.resourceTypes[cachedResource.type]; | |
| networkRequest.resourceSize = cachedResource.bodySize; | |
| this._updateNetworkRequestWithResponse(networkRequest, cachedResource.response); | |
| }, | |
| _isNull: function(response) | |
| { | |
| if (!response) | |
| return true; | |
| return !response.status && !response.mimeType && (!response.headers || !Object.keys(response.headers).length); | |
| }, | |
| requestWillBeSent: function(requestId, frameId, loaderId, documentURL, request, time, initiator, redirectResponse) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (networkRequest) { | |
| if (!redirectResponse) | |
| return; | |
| this.responseReceived(requestId, frameId, loaderId, time, "Other", redirectResponse); | |
| networkRequest = this._appendRedirect(requestId, time, request.url); | |
| } else | |
| networkRequest = this._createNetworkRequest(requestId, frameId, loaderId, request.url, documentURL, initiator); | |
| networkRequest.hasNetworkData = true; | |
| this._updateNetworkRequestWithRequest(networkRequest, request); | |
| networkRequest.startTime = time; | |
| this._startNetworkRequest(networkRequest); | |
| }, | |
| requestServedFromCache: function(requestId) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.cached = true; | |
| }, | |
| responseReceived: function(requestId, frameId, loaderId, time, resourceType, response) | |
| { | |
| if (this._isNull(response)) | |
| return; | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) { | |
| var eventData = {}; | |
| eventData.url = response.url; | |
| eventData.frameId = frameId; | |
| eventData.loaderId = loaderId; | |
| eventData.resourceType = resourceType; | |
| eventData.mimeType = response.mimeType; | |
| this._manager.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, eventData); | |
| return; | |
| } | |
| networkRequest.responseReceivedTime = time; | |
| networkRequest.type = WebInspector.resourceTypes[resourceType]; | |
| this._updateNetworkRequestWithResponse(networkRequest, response); | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| dataReceived: function(requestId, time, dataLength, encodedDataLength) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.resourceSize += dataLength; | |
| if (encodedDataLength != -1) | |
| networkRequest.increaseTransferSize(encodedDataLength); | |
| networkRequest.endTime = time; | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| loadingFinished: function(requestId, finishTime) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| this._finishNetworkRequest(networkRequest, finishTime); | |
| }, | |
| loadingFailed: function(requestId, time, localizedDescription, canceled) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.failed = true; | |
| networkRequest.canceled = canceled; | |
| networkRequest.localizedFailDescription = localizedDescription; | |
| this._finishNetworkRequest(networkRequest, time); | |
| }, | |
| requestServedFromMemoryCache: function(requestId, frameId, loaderId, documentURL, time, initiator, cachedResource) | |
| { | |
| var networkRequest = this._createNetworkRequest(requestId, frameId, loaderId, cachedResource.url, documentURL, initiator); | |
| this._updateNetworkRequestWithCachedResource(networkRequest, cachedResource); | |
| networkRequest.cached = true; | |
| networkRequest.requestMethod = "GET"; | |
| this._startNetworkRequest(networkRequest); | |
| networkRequest.startTime = networkRequest.responseReceivedTime = time; | |
| this._finishNetworkRequest(networkRequest, time); | |
| }, | |
| webSocketCreated: function(requestId, requestURL) | |
| { | |
| var networkRequest = new WebInspector.NetworkRequest(requestId, requestURL, "", "", ""); | |
| networkRequest.type = WebInspector.resourceTypes.WebSocket; | |
| this._startNetworkRequest(networkRequest); | |
| }, | |
| webSocketWillSendHandshakeRequest: function(requestId, time, request) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.requestMethod = "GET"; | |
| networkRequest.requestHeaders = this._headersMapToHeadersArray(request.headers); | |
| networkRequest.webSocketRequestKey3 = request.requestKey3; | |
| networkRequest.startTime = time; | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| webSocketHandshakeResponseReceived: function(requestId, time, response) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.statusCode = response.status; | |
| networkRequest.statusText = response.statusText; | |
| networkRequest.responseHeaders = this._headersMapToHeadersArray(response.headers); | |
| networkRequest.webSocketChallengeResponse = response.challengeResponse; | |
| networkRequest.responseReceivedTime = time; | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| webSocketFrameReceived: function(requestId, time, response) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.addFrame(response, time); | |
| networkRequest.responseReceivedTime = time; | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| webSocketFrameSent: function(requestId, time, response) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.addFrame(response, time, true); | |
| networkRequest.responseReceivedTime = time; | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| webSocketFrameError: function(requestId, time, errorMessage) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| networkRequest.addFrameError(errorMessage, time); | |
| networkRequest.responseReceivedTime = time; | |
| this._updateNetworkRequest(networkRequest); | |
| }, | |
| webSocketClosed: function(requestId, time) | |
| { | |
| var networkRequest = this._inflightRequestsById[requestId]; | |
| if (!networkRequest) | |
| return; | |
| this._finishNetworkRequest(networkRequest, time); | |
| }, | |
| _appendRedirect: function(requestId, time, redirectURL) | |
| { | |
| var originalNetworkRequest = this._inflightRequestsById[requestId]; | |
| var previousRedirects = originalNetworkRequest.redirects || []; | |
| originalNetworkRequest.requestId = "redirected:" + requestId + "." + previousRedirects.length; | |
| delete originalNetworkRequest.redirects; | |
| if (previousRedirects.length > 0) | |
| originalNetworkRequest.redirectSource = previousRedirects[previousRedirects.length - 1]; | |
| this._finishNetworkRequest(originalNetworkRequest, time); | |
| var newNetworkRequest = this._createNetworkRequest(requestId, originalNetworkRequest.frameId, originalNetworkRequest.loaderId, | |
| redirectURL, originalNetworkRequest.documentURL, originalNetworkRequest.initiator); | |
| newNetworkRequest.redirects = previousRedirects.concat(originalNetworkRequest); | |
| return newNetworkRequest; | |
| }, | |
| _startNetworkRequest: function(networkRequest) | |
| { | |
| this._inflightRequestsById[networkRequest.requestId] = networkRequest; | |
| this._inflightRequestsByURL[networkRequest.url] = networkRequest; | |
| this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestStarted, networkRequest); | |
| }, | |
| _updateNetworkRequest: function(networkRequest) | |
| { | |
| this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestUpdated, networkRequest); | |
| }, | |
| _finishNetworkRequest: function(networkRequest, finishTime) | |
| { | |
| networkRequest.endTime = finishTime; | |
| networkRequest.finished = true; | |
| this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, networkRequest); | |
| delete this._inflightRequestsById[networkRequest.requestId]; | |
| delete this._inflightRequestsByURL[networkRequest.url]; | |
| }, | |
| _dispatchEventToListeners: function(eventType, networkRequest) | |
| { | |
| this._manager.dispatchEventToListeners(eventType, networkRequest); | |
| }, | |
| _createNetworkRequest: function(requestId, frameId, loaderId, url, documentURL, initiator) | |
| { | |
| var networkRequest = new WebInspector.NetworkRequest(requestId, url, documentURL, frameId, loaderId); | |
| networkRequest.initiator = initiator; | |
| return networkRequest; | |
| } | |
| } | |
| WebInspector.networkManager = null; | |
| WebInspector.NetworkLog = function() | |
| { | |
| this._requests = []; | |
| this._requestForId = {}; | |
| WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoad, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._onDOMContentLoaded, this); | |
| } | |
| WebInspector.NetworkLog.prototype = { | |
| get requests() | |
| { | |
| return this._requests; | |
| }, | |
| pageLoadForRequest: function(request) | |
| { | |
| return request.__page; | |
| }, | |
| _onMainFrameNavigated: function(event) | |
| { | |
| var mainFrame = event.data; | |
| this._currentPageLoad = null; | |
| var oldRequests = this._requests.splice(0, this._requests.length); | |
| for (var i = 0; i < oldRequests.length; ++i) { | |
| var request = oldRequests[i]; | |
| if (request.loaderId === mainFrame.loaderId) { | |
| if (!this._currentPageLoad) | |
| this._currentPageLoad = new WebInspector.PageLoad(request); | |
| this._requests.push(request); | |
| request.__page = this._currentPageLoad; | |
| } | |
| } | |
| }, | |
| _onRequestStarted: function(event) | |
| { | |
| var request = event.data; | |
| this._requests.push(request); | |
| this._requestForId[request.requestId] = request; | |
| request.__page = this._currentPageLoad; | |
| }, | |
| _onDOMContentLoaded: function(event) | |
| { | |
| if (this._currentPageLoad) | |
| this._currentPageLoad.contentLoadTime = event.data; | |
| }, | |
| _onLoad: function(event) | |
| { | |
| if (this._currentPageLoad) | |
| this._currentPageLoad.loadTime = event.data; | |
| }, | |
| requestForId: function(requestId) | |
| { | |
| return this._requestForId[requestId]; | |
| } | |
| } | |
| WebInspector.networkLog = null; | |
| WebInspector.PageLoad = function(mainRequest) | |
| { | |
| this.id = ++WebInspector.PageLoad._lastIdentifier; | |
| this.url = mainRequest.url; | |
| this.startTime = mainRequest.startTime; | |
| } | |
| WebInspector.PageLoad._lastIdentifier = 0; | |
| WebInspector.ResourceTreeModel = function(networkManager) | |
| { | |
| networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); | |
| networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, this._onRequestUpdateDropped, this); | |
| WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); | |
| WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._consoleMessageAdded, this); | |
| WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); | |
| PageAgent.enable(); | |
| NetworkAgent.enable(); | |
| this._fetchResourceTree(); | |
| InspectorBackend.registerPageDispatcher(new WebInspector.PageDispatcher(this)); | |
| this._pendingConsoleMessages = {}; | |
| } | |
| WebInspector.ResourceTreeModel.EventTypes = { | |
| FrameAdded: "FrameAdded", | |
| FrameNavigated: "FrameNavigated", | |
| FrameDetached: "FrameDetached", | |
| MainFrameNavigated: "MainFrameNavigated", | |
| ResourceAdded: "ResourceAdded", | |
| WillLoadCachedResources: "WillLoadCachedResources", | |
| CachedResourcesLoaded: "CachedResourcesLoaded", | |
| DOMContentLoaded: "DOMContentLoaded", | |
| OnLoad: "OnLoad", | |
| InspectedURLChanged: "InspectedURLChanged" | |
| } | |
| WebInspector.ResourceTreeModel.prototype = { | |
| _fetchResourceTree: function() | |
| { | |
| this._frames = {}; | |
| delete this._cachedResourcesProcessed; | |
| PageAgent.getResourceTree(this._processCachedResources.bind(this)); | |
| }, | |
| _processCachedResources: function(error, mainFramePayload) | |
| { | |
| if (error) { | |
| console.error(JSON.stringify(error)); | |
| return; | |
| } | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources); | |
| WebInspector.inspectedPageURL = mainFramePayload.frame.url; | |
| this._addFramesRecursively(null, mainFramePayload); | |
| this._dispatchInspectedURLChanged(); | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded); | |
| this._cachedResourcesProcessed = true; | |
| }, | |
| cachedResourcesLoaded: function() | |
| { | |
| return this._cachedResourcesProcessed; | |
| }, | |
| _dispatchInspectedURLChanged: function() | |
| { | |
| InspectorFrontendHost.inspectedURLChanged(WebInspector.inspectedPageURL); | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, WebInspector.inspectedPageURL); | |
| }, | |
| _addFrame: function(frame) | |
| { | |
| this._frames[frame.id] = frame; | |
| if (frame.isMainFrame()) | |
| this.mainFrame = frame; | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame); | |
| }, | |
| _frameNavigated: function(framePayload) | |
| { | |
| if (!this._cachedResourcesProcessed) | |
| return; | |
| var frame = this._frames[framePayload.id]; | |
| if (frame) { | |
| frame._navigate(framePayload); | |
| } else { | |
| var parentFrame = this._frames[framePayload.parentId]; | |
| frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload); | |
| if (frame.isMainFrame() && this.mainFrame) { | |
| this._frameDetached(this.mainFrame.id); | |
| } | |
| this._addFrame(frame); | |
| } | |
| if (frame.isMainFrame()) | |
| WebInspector.inspectedPageURL = frame.url; | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frame); | |
| if (frame.isMainFrame()) | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, frame); | |
| var resources = frame.resources(); | |
| for (var i = 0; i < resources.length; ++i) | |
| this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resources[i]); | |
| if (frame.isMainFrame()) | |
| this._dispatchInspectedURLChanged(); | |
| }, | |
| _frameDetached: function(frameId) | |
| { | |
| if (!this._cachedResourcesProcessed) | |
| return; | |
| var frame = this._frames[frameId]; | |
| if (!frame) | |
| return; | |
| if (frame.parentFrame) | |
| frame.parentFrame._removeChildFrame(frame); | |
| else | |
| frame._remove(); | |
| }, | |
| _onRequestFinished: function(event) | |
| { | |
| if (!this._cachedResourcesProcessed) | |
| return; | |
| var request = event.data; | |
| if (request.failed || request.type === WebInspector.resourceTypes.XHR) | |
| return; | |
| var frame = this._frames[request.frameId]; | |
| if (frame) { | |
| var resource = frame._addRequest(request); | |
| this._addPendingConsoleMessagesToResource(resource); | |
| } | |
| }, | |
| _onRequestUpdateDropped: function(event) | |
| { | |
| if (!this._cachedResourcesProcessed) | |
| return; | |
| var frameId = event.data.frameId; | |
| var frame = this._frames[frameId]; | |
| if (!frame) | |
| return; | |
| var url = event.data.url; | |
| if (frame._resourcesMap[url]) | |
| return; | |
| var resource = new WebInspector.Resource(null, url, frame.url, frameId, event.data.loaderId, WebInspector.resourceTypes[event.data.resourceType], event.data.mimeType); | |
| frame.addResource(resource); | |
| }, | |
| frameForId: function(frameId) | |
| { | |
| return this._frames[frameId]; | |
| }, | |
| forAllResources: function(callback) | |
| { | |
| if (this.mainFrame) | |
| return this.mainFrame._callForFrameResources(callback); | |
| return false; | |
| }, | |
| _consoleMessageAdded: function(event) | |
| { | |
| var msg = event.data; | |
| var resource = msg.url ? this.resourceForURL(msg.url) : null; | |
| if (resource) | |
| this._addConsoleMessageToResource(msg, resource); | |
| else | |
| this._addPendingConsoleMessage(msg); | |
| }, | |
| _addPendingConsoleMessage: function(msg) | |
| { | |
| if (!msg.url) | |
| return; | |
| if (!this._pendingConsoleMessages[msg.url]) | |
| this._pendingConsoleMessages[msg.url] = []; | |
| this._pendingConsoleMessages[msg.url].push(msg); | |
| }, | |
| _addPendingConsoleMessagesToResource: function(resource) | |
| { | |
| var messages = this._pendingConsoleMessages[resource.url]; | |
| if (messages) { | |
| for (var i = 0; i < messages.length; i++) | |
| this._addConsoleMessageToResource(messages[i], resource); | |
| delete this._pendingConsoleMessages[resource.url]; | |
| } | |
| }, | |
| _addConsoleMessageToResource: function(msg, resource) | |
| { | |
| switch (msg.level) { | |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: | |
| resource.warnings += msg.repeatDelta; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Error: | |
| resource.errors += msg.repeatDelta; | |
| break; | |
| } | |
| resource.addMessage(msg); | |
| }, | |
| _consoleCleared: function() | |
| { | |
| function callback(resource) | |
| { | |
| resource.clearErrorsAndWarnings(); | |
| } | |
| this._pendingConsoleMessages = {}; | |
| this.forAllResources(callback); | |
| }, | |
| resourceForURL: function(url) | |
| { | |
| return this.mainFrame ? this.mainFrame.resourceForURL(url) : null; | |
| }, | |
| _addFramesRecursively: function(parentFrame, frameTreePayload) | |
| { | |
| var framePayload = frameTreePayload.frame; | |
| var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload); | |
| this._addFrame(frame); | |
| var frameResource = this._createResourceFromFramePayload(framePayload, framePayload.url, WebInspector.resourceTypes.Document, framePayload.mimeType); | |
| if (frame.isMainFrame()) | |
| WebInspector.inspectedPageURL = frameResource.url; | |
| frame.addResource(frameResource); | |
| for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i) | |
| this._addFramesRecursively(frame, frameTreePayload.childFrames[i]); | |
| for (var i = 0; i < frameTreePayload.resources.length; ++i) { | |
| var subresource = frameTreePayload.resources[i]; | |
| var resource = this._createResourceFromFramePayload(framePayload, subresource.url, WebInspector.resourceTypes[subresource.type], subresource.mimeType); | |
| frame.addResource(resource); | |
| } | |
| }, | |
| _createResourceFromFramePayload: function(frame, url, type, mimeType) | |
| { | |
| return new WebInspector.Resource(null, url, frame.url, frame.id, frame.loaderId, type, mimeType); | |
| } | |
| } | |
| WebInspector.ResourceTreeModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.ResourceTreeFrame = function(model, parentFrame, payload) | |
| { | |
| this._model = model; | |
| this._parentFrame = parentFrame; | |
| this._id = payload.id; | |
| this._loaderId = payload.loaderId; | |
| this._name = payload.name; | |
| this._url = payload.url; | |
| this._securityOrigin = payload.securityOrigin || ""; | |
| this._mimeType = payload.mimeType; | |
| this._childFrames = []; | |
| this._resourcesMap = {}; | |
| if (this._parentFrame) | |
| this._parentFrame._childFrames.push(this); | |
| } | |
| WebInspector.ResourceTreeFrame.prototype = { | |
| get id() | |
| { | |
| return this._id; | |
| }, | |
| get name() | |
| { | |
| return this._name || ""; | |
| }, | |
| get url() | |
| { | |
| return this._url; | |
| }, | |
| get securityOrigin() | |
| { | |
| return this._securityOrigin; | |
| }, | |
| get loaderId() | |
| { | |
| return this._loaderId; | |
| }, | |
| get parentFrame() | |
| { | |
| return this._parentFrame; | |
| }, | |
| get childFrames() | |
| { | |
| return this._childFrames; | |
| }, | |
| isMainFrame: function() | |
| { | |
| return !this._parentFrame; | |
| }, | |
| _navigate: function(framePayload) | |
| { | |
| this._loaderId = framePayload.loaderId; | |
| this._name = framePayload.name; | |
| this._url = framePayload.url; | |
| this._securityOrigin = framePayload.securityOrigin || ""; | |
| this._mimeType = framePayload.mimeType; | |
| var mainResource = this._resourcesMap[this._url]; | |
| this._resourcesMap = {}; | |
| this._removeChildFrames(); | |
| if (mainResource && mainResource.loaderId === this._loaderId) | |
| this.addResource(mainResource); | |
| }, | |
| get mainResource() | |
| { | |
| return this._resourcesMap[this._url]; | |
| }, | |
| _removeChildFrame: function(frame) | |
| { | |
| this._childFrames.remove(frame); | |
| frame._remove(); | |
| }, | |
| _removeChildFrames: function() | |
| { | |
| var copy = this._childFrames.slice(); | |
| for (var i = 0; i < copy.length; ++i) | |
| this._removeChildFrame(copy[i]); | |
| }, | |
| _remove: function() | |
| { | |
| this._removeChildFrames(); | |
| delete this._model._frames[this.id]; | |
| this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this); | |
| }, | |
| addResource: function(resource) | |
| { | |
| if (this._resourcesMap[resource.url] === resource) { | |
| return; | |
| } | |
| this._resourcesMap[resource.url] = resource; | |
| this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource); | |
| }, | |
| _addRequest: function(request) | |
| { | |
| var resource = this._resourcesMap[request.url]; | |
| if (resource && resource.request === request) { | |
| return resource; | |
| } | |
| resource = new WebInspector.Resource(request, request.url, request.documentURL, request.frameId, request.loaderId, request.type, request.mimeType); | |
| this._resourcesMap[resource.url] = resource; | |
| this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource); | |
| return resource; | |
| }, | |
| resources: function() | |
| { | |
| var result = []; | |
| for (var url in this._resourcesMap) | |
| result.push(this._resourcesMap[url]); | |
| return result; | |
| }, | |
| resourceForURL: function(url) | |
| { | |
| var result; | |
| function filter(resource) | |
| { | |
| if (resource.url === url) { | |
| result = resource; | |
| return true; | |
| } | |
| } | |
| this._callForFrameResources(filter); | |
| return result; | |
| }, | |
| _callForFrameResources: function(callback) | |
| { | |
| for (var url in this._resourcesMap) { | |
| if (callback(this._resourcesMap[url])) | |
| return true; | |
| } | |
| for (var i = 0; i < this._childFrames.length; ++i) { | |
| if (this._childFrames[i]._callForFrameResources(callback)) | |
| return true; | |
| } | |
| return false; | |
| } | |
| } | |
| WebInspector.PageDispatcher = function(resourceTreeModel) | |
| { | |
| this._resourceTreeModel = resourceTreeModel; | |
| } | |
| WebInspector.PageDispatcher.prototype = { | |
| domContentEventFired: function(time) | |
| { | |
| this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, time); | |
| }, | |
| loadEventFired: function(time) | |
| { | |
| this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.OnLoad, time); | |
| }, | |
| frameNavigated: function(frame) | |
| { | |
| this._resourceTreeModel._frameNavigated(frame); | |
| }, | |
| frameDetached: function(frameId) | |
| { | |
| this._resourceTreeModel._frameDetached(frameId); | |
| } | |
| } | |
| WebInspector.resourceTreeModel = null; | |
| WebInspector.ParsedURL = function(url) | |
| { | |
| this.isValid = false; | |
| this.url = url; | |
| this.scheme = ""; | |
| this.host = ""; | |
| this.port = ""; | |
| this.path = ""; | |
| this.queryParams = ""; | |
| this.fragment = ""; | |
| this.folderPathComponents = ""; | |
| this.lastPathComponent = ""; | |
| var match = url.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i); | |
| if (match) { | |
| this.isValid = true; | |
| this.scheme = match[1].toLowerCase(); | |
| this.host = match[2]; | |
| this.port = match[3]; | |
| this.path = match[4] || "/"; | |
| this.fragment = match[5]; | |
| } else { | |
| if (this.url.startsWith("data:")) { | |
| this.scheme = "data"; | |
| return; | |
| } | |
| if (this.url === "about:blank") { | |
| this.scheme = "about"; | |
| return; | |
| } | |
| this.path = this.url; | |
| } | |
| if (this.path) { | |
| var path = this.path; | |
| var indexOfQuery = path.indexOf("?"); | |
| if (indexOfQuery !== -1) { | |
| this.queryParams = path.substring(indexOfQuery + 1) | |
| path = path.substring(0, indexOfQuery); | |
| } | |
| var lastSlashIndex = path.lastIndexOf("/"); | |
| if (lastSlashIndex !== -1) { | |
| this.folderPathComponents = path.substring(0, lastSlashIndex); | |
| this.lastPathComponent = path.substring(lastSlashIndex + 1); | |
| } else | |
| this.lastPathComponent = path; | |
| } | |
| } | |
| WebInspector.ParsedURL.completeURL = function(baseURL, href) | |
| { | |
| if (href) { | |
| var trimmedHref = href.trim(); | |
| if (trimmedHref.startsWith("data:") || trimmedHref.startsWith("blob:") || trimmedHref.startsWith("javascript:")) | |
| return href; | |
| var parsedHref = trimmedHref.asParsedURL(); | |
| if (parsedHref && parsedHref.scheme) | |
| return trimmedHref; | |
| } else | |
| return baseURL; | |
| var parsedURL = baseURL.asParsedURL(); | |
| if (parsedURL) { | |
| var path = href; | |
| if (path.charAt(0) !== "/") { | |
| var basePath = parsedURL.path; | |
| var questionMarkIndex = basePath.indexOf("?"); | |
| if (questionMarkIndex > 0) | |
| basePath = basePath.substring(0, questionMarkIndex); | |
| var prefix; | |
| if (path.charAt(0) === "?") { | |
| var basePathCutIndex = basePath.indexOf("?"); | |
| if (basePathCutIndex !== -1) | |
| prefix = basePath.substring(0, basePathCutIndex); | |
| else | |
| prefix = basePath; | |
| } else | |
| prefix = basePath.substring(0, basePath.lastIndexOf("/")) + "/"; | |
| path = prefix + path; | |
| } else if (path.length > 1 && path.charAt(1) === "/") { | |
| return parsedURL.scheme + ":" + path; | |
| } | |
| return parsedURL.scheme + "://" + parsedURL.host + (parsedURL.port ? (":" + parsedURL.port) : "") + path; | |
| } | |
| return null; | |
| } | |
| WebInspector.ParsedURL.prototype = { | |
| get displayName() | |
| { | |
| if (this._displayName) | |
| return this._displayName; | |
| if (this.scheme === "data") { | |
| this._displayName = this.url.trimEnd(20); | |
| return this._displayName; | |
| } | |
| if (this.url === "about:blank") | |
| return this.url; | |
| this._displayName = this.lastPathComponent; | |
| if (!this._displayName) | |
| this._displayName = this.host; | |
| if (!this._displayName && this.url) | |
| this._displayName = this.url.trimURL(WebInspector.inspectedPageDomain ? WebInspector.inspectedPageDomain : ""); | |
| if (this._displayName === "/") | |
| this._displayName = this.url; | |
| return this._displayName; | |
| } | |
| } | |
| String.prototype.asParsedURL = function() | |
| { | |
| var parsedURL = new WebInspector.ParsedURL(this.toString()); | |
| if (parsedURL.isValid) | |
| return parsedURL; | |
| return null; | |
| } | |
| WebInspector.resourceForURL = function(url) | |
| { | |
| return WebInspector.resourceTreeModel.resourceForURL(url); | |
| } | |
| WebInspector.forAllResources = function(callback) | |
| { | |
| WebInspector.resourceTreeModel.forAllResources(callback); | |
| } | |
| WebInspector.displayNameForURL = function(url) | |
| { | |
| if (!url) | |
| return ""; | |
| var resource = WebInspector.resourceForURL(url); | |
| if (resource) | |
| return resource.displayName; | |
| if (!WebInspector.inspectedPageURL) | |
| return url.trimURL(""); | |
| var parsedURL = WebInspector.inspectedPageURL.asParsedURL(); | |
| var lastPathComponent = parsedURL ? parsedURL.lastPathComponent : parsedURL; | |
| var index = WebInspector.inspectedPageURL.indexOf(lastPathComponent); | |
| if (index !== -1 && index + lastPathComponent.length === WebInspector.inspectedPageURL.length) { | |
| var baseURL = WebInspector.inspectedPageURL.substring(0, index); | |
| if (url.startsWith(baseURL)) | |
| return url.substring(index); | |
| } | |
| return parsedURL ? url.trimURL(parsedURL.host) : url; | |
| } | |
| WebInspector.linkifyStringAsFragmentWithCustomLinkifier = function(string, linkifier) | |
| { | |
| var container = document.createDocumentFragment(); | |
| var linkStringRegEx = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/|www\.)[\w$\-_+*'=\|\/\\(){}[\]%@&#~,:;.!?]{2,}[\w$\-_+*=\|\/\\({%@&#~]/; | |
| var lineColumnRegEx = /:(\d+)(:(\d+))?$/; | |
| while (string) { | |
| var linkString = linkStringRegEx.exec(string); | |
| if (!linkString) | |
| break; | |
| linkString = linkString[0]; | |
| var linkIndex = string.indexOf(linkString); | |
| var nonLink = string.substring(0, linkIndex); | |
| container.appendChild(document.createTextNode(nonLink)); | |
| var title = linkString; | |
| var realURL = (linkString.startsWith("www.") ? "http://" + linkString : linkString); | |
| var lineColumnMatch = lineColumnRegEx.exec(realURL); | |
| var lineNumber; | |
| if (lineColumnMatch) { | |
| realURL = realURL.substring(0, realURL.length - lineColumnMatch[0].length); | |
| lineNumber = parseInt(lineColumnMatch[1], 10); | |
| lineNumber = isNaN(lineNumber) ? undefined : lineNumber; | |
| } | |
| var linkNode = linkifier(title, realURL, lineNumber); | |
| container.appendChild(linkNode); | |
| string = string.substring(linkIndex + linkString.length, string.length); | |
| } | |
| if (string) | |
| container.appendChild(document.createTextNode(string)); | |
| return container; | |
| } | |
| WebInspector._linkifierPlugins = []; | |
| /** | |
| * @param {function(string):string} plugin | |
| */ | |
| WebInspector.registerLinkifierPlugin = function(plugin) | |
| { | |
| WebInspector._linkifierPlugins.push(plugin); | |
| } | |
| /** | |
| * @param {string} string | |
| * @return {DocumentFragment} | |
| */ | |
| WebInspector.linkifyStringAsFragment = function(string) | |
| { | |
| /** | |
| * @param {string} title | |
| * @param {string} url | |
| * @param {number=} lineNumber | |
| * @return {Node} | |
| */ | |
| function linkifier(title, url, lineNumber) | |
| { | |
| for (var i = 0; i < WebInspector._linkifierPlugins.length; ++i) | |
| title = WebInspector._linkifierPlugins[i](title); | |
| var isExternal = !WebInspector.resourceForURL(url); | |
| var urlNode = WebInspector.linkifyURLAsNode(url, title, undefined, isExternal); | |
| if (typeof(lineNumber) !== "undefined") { | |
| urlNode.lineNumber = lineNumber; | |
| urlNode.preferredPanel = "scripts"; | |
| } | |
| return urlNode; | |
| } | |
| return WebInspector.linkifyStringAsFragmentWithCustomLinkifier(string, linkifier); | |
| } | |
| /** | |
| * @param {string} url | |
| * @param {string=} linkText | |
| * @param {string=} classes | |
| * @param {boolean=} isExternal | |
| * @param {string=} tooltipText | |
| * @return {Element} | |
| */ | |
| WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, tooltipText) | |
| { | |
| if (!linkText) | |
| linkText = url; | |
| classes = (classes ? classes + " " : ""); | |
| classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link"; | |
| var a = document.createElement("a"); | |
| a.href = sanitizeHref(url); | |
| a.className = classes; | |
| if (typeof tooltipText === "undefined") | |
| a.title = url; | |
| else if (typeof tooltipText !== "string" || tooltipText.length) | |
| a.title = tooltipText; | |
| a.textContent = linkText; | |
| a.style.maxWidth = "100%"; | |
| if (isExternal) | |
| a.setAttribute("target", "_blank"); | |
| return a; | |
| } | |
| /** | |
| * @param {string} url | |
| * @param {number=} lineNumber | |
| * @return {string} | |
| */ | |
| WebInspector.formatLinkText = function(url, lineNumber) | |
| { | |
| var text = WebInspector.displayNameForURL(url); | |
| if (typeof lineNumber === "number") | |
| text += ":" + (lineNumber + 1); | |
| return text; | |
| } | |
| /** | |
| * @param {string} url | |
| * @param {number=} lineNumber | |
| * @param {string=} classes | |
| * @param {string=} tooltipText | |
| * @return {Element} | |
| */ | |
| WebInspector.linkifyResourceAsNode = function(url, lineNumber, classes, tooltipText) | |
| { | |
| var linkText = WebInspector.formatLinkText(url, lineNumber); | |
| var anchor = WebInspector.linkifyURLAsNode(url, linkText, classes, false, tooltipText); | |
| anchor.preferredPanel = "resources"; | |
| anchor.lineNumber = lineNumber; | |
| return anchor; | |
| } | |
| /** | |
| * @param {WebInspector.NetworkRequest} request | |
| * @param {string=} classes | |
| * @return {Element} | |
| */ | |
| WebInspector.linkifyRequestAsNode = function(request, classes) | |
| { | |
| var anchor = WebInspector.linkifyURLAsNode(request.url); | |
| anchor.preferredPanel = "network"; | |
| anchor.requestId = request.requestId; | |
| return anchor; | |
| } | |
| /* ResourceType.js */ | |
| /* | |
| * Copyright (C) 2012 Google Inc. All rights reserved. | |
| * Copyright (C) 2007, 2008 Apple 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: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. 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. | |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 | |
| * @param {string} name | |
| * @param {string} title | |
| * @param {string} categoryTitle | |
| * @param {string} color | |
| * @param {boolean} isTextType | |
| */ | |
| WebInspector.ResourceType = function(name, title, categoryTitle, color, isTextType) | |
| { | |
| this._name = name; | |
| this._title = title; | |
| this._categoryTitle = categoryTitle; | |
| this._color = color; | |
| this._isTextType = isTextType; | |
| } | |
| WebInspector.ResourceType.prototype = { | |
| /** | |
| * @return {string} | |
| */ | |
| name: function() | |
| { | |
| return this._name; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| title: function() | |
| { | |
| return this._title; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| categoryTitle: function() | |
| { | |
| return this._categoryTitle; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| color: function() | |
| { | |
| return this._color; | |
| }, | |
| /** | |
| * @return {boolean} | |
| */ | |
| isTextType: function() | |
| { | |
| return this._isTextType; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| toString: function() | |
| { | |
| return this._name; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| canonicalMimeType: function() | |
| { | |
| if (this === WebInspector.resourceTypes.Document) | |
| return "text/html"; | |
| if (this === WebInspector.resourceTypes.Script) | |
| return "text/javascript"; | |
| if (this === WebInspector.resourceTypes.Stylesheet) | |
| return "text/css"; | |
| return ""; | |
| } | |
| } | |
| //Keep these in sync with WebCore::InspectorPageAgent::resourceTypeJson | |
| WebInspector.resourceTypes = { | |
| Document: new WebInspector.ResourceType("document", "Document", "Documents", "rgb(47,102,236)", true), | |
| Stylesheet: new WebInspector.ResourceType("stylesheet", "Stylesheet", "Stylesheets", "rgb(157,231,119)", true), | |
| Image: new WebInspector.ResourceType("image", "Image", "Images", "rgb(164,60,255)", false), | |
| Script: new WebInspector.ResourceType("script", "Script", "Scripts", "rgb(255,121,0)", true), | |
| XHR: new WebInspector.ResourceType("xhr", "XHR", "XHR", "rgb(231,231,10)", true), | |
| Font: new WebInspector.ResourceType("font", "Font", "Fonts", "rgb(255,82,62)", false), | |
| WebSocket: new WebInspector.ResourceType("websocket", "WebSocket", "WebSockets", "rgb(186,186,186)", false), // FIXME: Decide the color. | |
| Other: new WebInspector.ResourceType("other", "Other", "Other", "rgb(186,186,186)", false) | |
| } | |
| /* TimelineManager.js */ | |
| /* | |
| * Copyright (C) 2011 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 | |
| * @extends {WebInspector.Object} | |
| */ | |
| WebInspector.TimelineManager = function() | |
| { | |
| WebInspector.Object.call(this); | |
| this._dispatcher = new WebInspector.TimelineDispatcher(this); | |
| this._enablementCount = 0; | |
| } | |
| WebInspector.TimelineManager.EventTypes = { | |
| TimelineStarted: "TimelineStarted", | |
| TimelineStopped: "TimelineStopped", | |
| TimelineEventRecorded: "TimelineEventRecorded" | |
| } | |
| WebInspector.TimelineManager.prototype = { | |
| /** | |
| * @param {number=} maxCallStackDepth | |
| */ | |
| start: function(maxCallStackDepth) | |
| { | |
| this._enablementCount++; | |
| if (this._enablementCount === 1) | |
| TimelineAgent.start(maxCallStackDepth, this._started.bind(this)); | |
| }, | |
| stop: function() | |
| { | |
| if (!this._enablementCount) { | |
| console.error("WebInspector.TimelineManager start/stop calls are unbalanced"); | |
| return; | |
| } | |
| this._enablementCount--; | |
| if (!this._enablementCount) | |
| TimelineAgent.stop(this._stopped.bind(this)); | |
| }, | |
| _started: function() | |
| { | |
| this.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStarted); | |
| }, | |
| _stopped: function() | |
| { | |
| this.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStopped); | |
| } | |
| } | |
| WebInspector.TimelineManager.prototype.__proto__ = WebInspector.Object.prototype; | |
| /** | |
| * @constructor | |
| * @implements {TimelineAgent.Dispatcher} | |
| */ | |
| WebInspector.TimelineDispatcher = function(manager) | |
| { | |
| this._manager = manager; | |
| InspectorBackend.registerTimelineDispatcher(this); | |
| } | |
| WebInspector.TimelineDispatcher.prototype = { | |
| eventRecorded: function(record) | |
| { | |
| this._manager.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, record); | |
| } | |
| } | |
| /** | |
| * @type {WebInspector.TimelineManager} | |
| */ | |
| WebInspector.timelineManager; | |
| /* UserAgentSupport.js */ | |
| /* | |
| * Copyright (C) 2012 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 | |
| */ | |
| WebInspector.UserAgentSupport = function() | |
| { | |
| if (WebInspector.settings.deviceMetrics.get()) | |
| this._deviceMetricsChanged(); | |
| WebInspector.settings.deviceMetrics.addChangeListener(this._deviceMetricsChanged, this); | |
| WebInspector.settings.deviceFitWindow.addChangeListener(this._deviceMetricsChanged, this); | |
| WebInspector.settings.geolocationOverride.addChangeListener(this._geolocationPositionChanged, this); | |
| WebInspector.settings.deviceOrientationOverride.addChangeListener(this._deviceOrientationChanged, this); | |
| } | |
| /** | |
| * @constructor | |
| * @param {number} width | |
| * @param {number} height | |
| * @param {number} fontScaleFactor | |
| */ | |
| WebInspector.UserAgentSupport.DeviceMetrics = function(width, height, fontScaleFactor) | |
| { | |
| this.width = width; | |
| this.height = height; | |
| this.fontScaleFactor = fontScaleFactor; | |
| } | |
| /** | |
| * @return {WebInspector.UserAgentSupport.DeviceMetrics} | |
| */ | |
| WebInspector.UserAgentSupport.DeviceMetrics.parseSetting = function(value) | |
| { | |
| if (value) { | |
| var splitMetrics = value.split("x"); | |
| if (splitMetrics.length === 3) | |
| return new WebInspector.UserAgentSupport.DeviceMetrics(parseInt(splitMetrics[0], 10), parseInt(splitMetrics[1], 10), parseFloat(splitMetrics[2])); | |
| } | |
| return new WebInspector.UserAgentSupport.DeviceMetrics(0, 0, 1); | |
| } | |
| /** | |
| * @return {?WebInspector.UserAgentSupport.DeviceMetrics} | |
| */ | |
| WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput = function(widthString, heightString, fontScaleFactorString) | |
| { | |
| function isUserInputValid(value, isInteger) | |
| { | |
| if (!value) | |
| return true; | |
| return isInteger ? /^[0]*[1-9][\d]*$/.test(value) : /^[0]*([1-9][\d]*(\.\d+)?|\.\d+)$/.test(value); | |
| } | |
| if (!widthString ^ !heightString) | |
| return null; | |
| var isWidthValid = isUserInputValid(widthString, true); | |
| var isHeightValid = isUserInputValid(heightString, true); | |
| var isFontScaleFactorValid = isUserInputValid(fontScaleFactorString, false); | |
| if (!isWidthValid && !isHeightValid && !isFontScaleFactorValid) | |
| return null; | |
| var width = isWidthValid ? parseInt(widthString || "0", 10) : -1; | |
| var height = isHeightValid ? parseInt(heightString || "0", 10) : -1; | |
| var fontScaleFactor = isFontScaleFactorValid ? parseFloat(fontScaleFactorString) : -1; | |
| return new WebInspector.UserAgentSupport.DeviceMetrics(width, height, fontScaleFactor); | |
| } | |
| WebInspector.UserAgentSupport.DeviceMetrics.prototype = { | |
| /** | |
| * @return {boolean} | |
| */ | |
| isValid: function() | |
| { | |
| return this.isWidthValid() && this.isHeightValid() && this.isFontScaleFactorValid(); | |
| }, | |
| /** | |
| * @return {boolean} | |
| */ | |
| isWidthValid: function() | |
| { | |
| return this.width >= 0; | |
| }, | |
| /** | |
| * @return {boolean} | |
| */ | |
| isHeightValid: function() | |
| { | |
| return this.height >= 0; | |
| }, | |
| /** | |
| * @return {boolean} | |
| */ | |
| isFontScaleFactorValid: function() | |
| { | |
| return this.fontScaleFactor > 0; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| toSetting: function() | |
| { | |
| if (!this.isValid()) | |
| return ""; | |
| return this.width && this.height ? this.width + "x" + this.height + "x" + this.fontScaleFactor : ""; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| widthToInput: function() | |
| { | |
| return this.isWidthValid() && this.width ? String(this.width) : ""; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| heightToInput: function() | |
| { | |
| return this.isHeightValid() && this.height ? String(this.height) : ""; | |
| }, | |
| /** | |
| * @return {string} | |
| */ | |
| fontScaleFactorToInput: function() | |
| { | |
| return this.isFontScaleFactorValid() && this.fontScaleFactor ? String(this.fontScaleFactor) : ""; | |
| } | |
| } | |
| /** | |
| * @constructor | |
| * @param {number} latitude | |
| * @param {number} longitude | |
| */ | |
| WebInspector.UserAgentSupport.GeolocationPosition = function(latitude, longitude, error) | |
| { | |
| this.latitude = latitude; | |
| this.longitude = longitude; | |
| this.error = error; | |
| } | |
| WebInspector.UserAgentSupport.GeolocationPosition.prototype = { | |
| /** | |
| * @return {string} | |
| */ | |
| toSetting: function() | |
| { | |
| return (typeof this.latitude === "number" && typeof this.longitude === "number" && typeof this.error === "string") ? this.latitude + "@" + this.longitude + ":" + this.error : ""; | |
| } | |
| } | |
| /** | |
| * @return {WebInspector.UserAgentSupport.GeolocationPosition} | |
| */ | |
| WebInspector.UserAgentSupport.GeolocationPosition.parseSetting = function(value) | |
| { | |
| if (value) { | |
| var splitError = value.split(":"); | |
| if (splitError.length === 2) { | |
| var splitPosition = splitError[0].split("@") | |
| if (splitPosition.length === 2) | |
| return new WebInspector.UserAgentSupport.GeolocationPosition(parseFloat(splitPosition[0]), parseFloat(splitPosition[1]), splitError[1]); | |
| } | |
| } | |
| return new WebInspector.UserAgentSupport.GeolocationPosition(0, 0, ""); | |
| } | |
| /** | |
| * @return {?WebInspector.UserAgentSupport.GeolocationPosition} | |
| */ | |
| WebInspector.UserAgentSupport.GeolocationPosition.parseUserInput = function(latitudeString, longitudeString, errorStatus) | |
| { | |
| function isUserInputValid(value) | |
| { | |
| if (!value) | |
| return true; | |
| return /^[-]?[0-9]*[.]?[0-9]*$/.test(value); | |
| } | |
| if (!latitudeString ^ !latitudeString) | |
| return null; | |
| var isLatitudeValid = isUserInputValid(latitudeString); | |
| var isLongitudeValid = isUserInputValid(longitudeString); | |
| if (!isLatitudeValid && !isLongitudeValid) | |
| return null; | |
| var latitude = isLatitudeValid ? parseFloat(latitudeString) : -1; | |
| var longitude = isLongitudeValid ? parseFloat(longitudeString) : -1; | |
| return new WebInspector.UserAgentSupport.GeolocationPosition(latitude, longitude, errorStatus ? "PositionUnavailable" : ""); | |
| } | |
| WebInspector.UserAgentSupport.GeolocationPosition.clearGeolocationOverride = function() | |
| { | |
| PageAgent.clearGeolocationOverride(); | |
| } | |
| /** | |
| * @constructor | |
| * @param {number} alpha | |
| * @param {number} beta | |
| * @param {number} gamma | |
| */ | |
| WebInspector.UserAgentSupport.DeviceOrientation = function(alpha, beta, gamma) | |
| { | |
| this.alpha = alpha; | |
| this.beta = beta; | |
| this.gamma = gamma; | |
| } | |
| WebInspector.UserAgentSupport.DeviceOrientation.prototype = { | |
| /** | |
| * @return {string} | |
| */ | |
| toSetting: function() | |
| { | |
| return JSON.stringify(this); | |
| } | |
| } | |
| /** | |
| * @return {WebInspector.UserAgentSupport.DeviceOrientation} | |
| */ | |
| WebInspector.UserAgentSupport.DeviceOrientation.parseSetting = function(value) | |
| { | |
| if (value) { | |
| var jsonObject = JSON.parse(value); | |
| return new WebInspector.UserAgentSupport.DeviceOrientation(jsonObject.alpha, jsonObject.beta, jsonObject.gamma); | |
| } | |
| return new WebInspector.UserAgentSupport.DeviceOrientation(0, 0, 0); | |
| } | |
| /** | |
| * @return {?WebInspector.UserAgentSupport.DeviceOrientation} | |
| */ | |
| WebInspector.UserAgentSupport.DeviceOrientation.parseUserInput = function(alphaString, betaString, gammaString) | |
| { | |
| function isUserInputValid(value) | |
| { | |
| if (!value) | |
| return true; | |
| return /^[-]?[0-9]*[.]?[0-9]*$/.test(value); | |
| } | |
| if (!alphaString ^ !betaString ^ !gammaString) | |
| return null; | |
| var isAlphaValid = isUserInputValid(alphaString); | |
| var isBetaValid = isUserInputValid(betaString); | |
| var isGammaValid = isUserInputValid(gammaString); | |
| if (!isAlphaValid && !isBetaValid && !isGammaValid) | |
| return null; | |
| var alpha = isAlphaValid ? parseFloat(alphaString) : -1; | |
| var beta = isBetaValid ? parseFloat(betaString) : -1; | |
| var gamma = isGammaValid ? parseFloat(gammaString) : -1; | |
| return new WebInspector.UserAgentSupport.DeviceOrientation(alpha, beta, gamma); | |
| } | |
| WebInspector.UserAgentSupport.DeviceOrientation.clearDeviceOrientationOverride = function() | |
| { | |
| PageAgent.clearDeviceOrientationOverride(); | |
| } | |
| WebInspector.UserAgentSupport.prototype = { | |
| _deviceMetricsChanged: function() | |
| { | |
| var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(WebInspector.settings.deviceMetrics.get()); | |
| if (metrics.isValid()) | |
| PageAgent.setDeviceMetricsOverride(metrics.width, metrics.height, metrics.fontScaleFactor, WebInspector.settings.deviceFitWindow.get()); | |
| }, | |
| _geolocationPositionChanged: function() | |
| { | |
| var geolocation = WebInspector.UserAgentSupport.GeolocationPosition.parseSetting(WebInspector.settings.geolocationOverride.get()); | |
| if (geolocation.error) | |
| PageAgent.setGeolocationOverride(); | |
| else | |
| PageAgent.setGeolocationOverride(geolocation.latitude, geolocation.longitude, 150); | |
| }, | |
| /** | |
| * @param {WebInspector.Event} event | |
| */ | |
| _deviceOrientationChanged: function(event) | |
| { | |
| var deviceOrientation = WebInspector.UserAgentSupport.DeviceOrientation.parseSetting(WebInspector.settings.deviceOrientationOverride.get()); | |
| PageAgent.setDeviceOrientationOverride(deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma); | |
| } | |
| } | |
| /* Database.js */ | |
| /* | |
| * Copyright (C) 2007, 2008 Apple 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: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. 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. | |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 | |
| * @param {WebInspector.DatabaseModel} model | |
| */ | |
| WebInspector.Database = function(model, id, domain, name, version) | |
| { | |
| this._model = model; | |
| this._id = id; | |
| this._domain = domain; | |
| this._name = name; | |
| this._version = version; | |
| } | |
| WebInspector.Database.prototype = { | |
| /** @return {string} */ | |
| get id() | |
| { | |
| return this._id; | |
| }, | |
| /** @return {string} */ | |
| get name() | |
| { | |
| return this._name; | |
| }, | |
| set name(x) | |
| { | |
| this._name = x; | |
| }, | |
| /** @return {string} */ | |
| get version() | |
| { | |
| return this._version; | |
| }, | |
| set version(x) | |
| { | |
| this._version = x; | |
| }, | |
| /** @return {string} */ | |
| get domain() | |
| { | |
| return this._domain; | |
| }, | |
| set domain(x) | |
| { | |
| this._domain = x; | |
| }, | |
| /** | |
| * @param {function(Array.<string>)} callback | |
| */ | |
| getTableNames: function(callback) | |
| { | |
| function sortingCallback(error, names) | |
| { | |
| if (!error) | |
| callback(names.sort()); | |
| } | |
| DatabaseAgent.getDatabaseTableNames(this._id, sortingCallback); | |
| }, | |
| /** | |
| * @param {string} query | |
| * @param {function(Array.<string>=, Array.<*>=)} onSuccess | |
| * @param {function(string)} onError | |
| */ | |
| executeSql: function(query, onSuccess, onError) | |
| { | |
| /** | |
| * @param {?Protocol.Error} error | |
| * @param {Array.<string>=} columnNames | |
| * @param {Array.<*>=} values | |
| * @param {DatabaseAgent.Error=} errorObj | |
| */ | |
| function callback(error, columnNames, values, errorObj) | |
| { | |
| if (error) { | |
| onError(error); | |
| return; | |
| } | |
| if (errorObj) { | |
| var message; | |
| if (errorObj.message) | |
| message = errorObj.message; | |
| else if (errorObj.code == 2) | |
| message = WebInspector.UIString("Database no longer has expected version."); | |
| else | |
| message = WebInspector.UIString("An unexpected error %s occurred.", errorObj.code); | |
| onError(message); | |
| return; | |
| } | |
| onSuccess(columnNames, values); | |
| } | |
| DatabaseAgent.executeSQL(this._id, query, callback.bind(this)); | |
| } | |
| } | |
| /** | |
| * @constructor | |
| * @extends {WebInspector.Object} | |
| */ | |
| WebInspector.DatabaseModel = function() | |
| { | |
| this._databases = []; | |
| InspectorBackend.registerDatabaseDispatcher(new WebInspector.DatabaseDispatcher(this)); | |
| DatabaseAgent.enable(); | |
| } | |
| WebInspector.DatabaseModel.Events = { | |
| DatabaseAdded: "DatabaseAdded" | |
| } | |
| WebInspector.DatabaseModel.prototype = { | |
| /** | |
| * @return {Array.<WebInspector.Database>} | |
| */ | |
| databases: function() | |
| { | |
| var result = []; | |
| for (var databaseId in this._databases) | |
| result.push(this._databases[databaseId]); | |
| return result; | |
| }, | |
| /** | |
| * @param {DatabaseAgent.DatabaseId} databaseId | |
| * @return {WebInspector.Database} | |
| */ | |
| databaseForId: function(databaseId) | |
| { | |
| return this._databases[databaseId]; | |
| }, | |
| /** | |
| * @param {WebInspector.Database} database | |
| */ | |
| _addDatabase: function(database) | |
| { | |
| this._databases.push(database); | |
| this.dispatchEventToListeners(WebInspector.DatabaseModel.Events.DatabaseAdded, database); | |
| } | |
| } | |
| WebInspector.DatabaseModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| /** | |
| * @constructor | |
| * @implements {DatabaseAgent.Dispatcher} | |
| * @param {WebInspector.DatabaseModel} model | |
| */ | |
| WebInspector.DatabaseDispatcher = function(model) | |
| { | |
| this._model = model; | |
| } | |
| WebInspector.DatabaseDispatcher.prototype = { | |
| /** | |
| * @param {DatabaseAgent.Database} payload | |
| */ | |
| addDatabase: function(payload) | |
| { | |
| this._model._addDatabase(new WebInspector.Database( | |
| this._model, | |
| payload.id, | |
| payload.domain, | |
| payload.name, | |
| payload.version)); | |
| } | |
| } | |
| /** | |
| * @type {WebInspector.DatabaseModel} | |
| */ | |
| WebInspector.databaseModel = null; | |
| /* DOMStorage.js */ | |
| /* | |
| * Copyright (C) 2008 Nokia 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: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. 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. | |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 "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 APPLE OR ITS 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 | |
| */ | |
| WebInspector.DOMStorage = function(id, domain, isLocalStorage) | |
| { | |
| this._id = id; | |
| this._domain = domain; | |
| this._isLocalStorage = isLocalStorage; | |
| } | |
| WebInspector.DOMStorage.prototype = { | |
| /** @return {string} */ | |
| get id() | |
| { | |
| return this._id; | |
| }, | |
| /** @return {string} */ | |
| get domain() | |
| { | |
| return this._domain; | |
| }, | |
| /** @return {boolean} */ | |
| get isLocalStorage() | |
| { | |
| return this._isLocalStorage; | |
| }, | |
| /** | |
| * @param {function(?Protocol.Error, Array.<DOMStorageAgent.Entry>):void=} callback | |
| */ | |
| getEntries: function(callback) | |
| { | |
| DOMStorageAgent.getDOMStorageEntries(this._id, callback); | |
| }, | |
| /** | |
| * @param {string} key | |
| * @param {string} value | |
| * @param {function(?Protocol.Error, boolean):void=} callback | |
| */ | |
| setItem: function(key, value, callback) | |
| { | |
| DOMStorageAgent.setDOMStorageItem(this._id, key, value, callback); | |
| }, | |
| /** | |
| * @param {string} key | |
| * @param {function(?Protocol.Error, boolean):void=} callback | |
| */ | |
| removeItem: function(key, callback) | |
| { | |
| DOMStorageAgent.removeDOMStorageItem(this._id, key, callback); | |
| } | |
| } | |
| /** | |
| * @constructor | |
| * @extends {WebInspector.Object} | |
| */ | |
| WebInspector.DOMStorageModel = function() | |
| { | |
| this._storages = {}; | |
| InspectorBackend.registerDOMStorageDispatcher(new WebInspector.DOMStorageDispatcher(this)); | |
| DOMStorageAgent.enable(); | |
| } | |
| WebInspector.DOMStorageModel.Events = { | |
| DOMStorageAdded: "DOMStorageAdded", | |
| DOMStorageUpdated: "DOMStorageUpdated" | |
| } | |
| WebInspector.DOMStorageModel.prototype = { | |
| /** | |
| * @param {WebInspector.DOMStorage} domStorage | |
| */ | |
| _addDOMStorage: function(domStorage) | |
| { | |
| this._storages[domStorage.id] = domStorage; | |
| this.dispatchEventToListeners(WebInspector.DOMStorageModel.Events.DOMStorageAdded, domStorage); | |
| }, | |
| /** | |
| * @param {DOMStorageAgent.StorageId} storageId | |
| */ | |
| _domStorageUpdated: function(storageId) | |
| { | |
| this.dispatchEventToListeners(WebInspector.DOMStorageModel.Events.DOMStorageUpdated, this._storages[storageId]); | |
| }, | |
| /** | |
| * @param {DOMStorageAgent.StorageId} storageId | |
| * @return {WebInspector.DOMStorage} | |
| */ | |
| storageForId: function(storageId) | |
| { | |
| return this._storages[storageId]; | |
| }, | |
| /** | |
| * @return {Array.<WebInspector.DOMStorage>} | |
| */ | |
| storages: function() | |
| { | |
| var result = []; | |
| for (var storageId in this._storages) | |
| result.push(this._storages[storageId]); | |
| return result; | |
| } | |
| } | |
| WebInspector.DOMStorageModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| /** | |
| * @constructor | |
| * @implements {DOMStorageAgent.Dispatcher} | |
| * @param {WebInspector.DOMStorageModel} model | |
| */ | |
| WebInspector.DOMStorageDispatcher = function(model) | |
| { | |
| this._model = model; | |
| } | |
| WebInspector.DOMStorageDispatcher.prototype = { | |
| /** | |
| * @param {DOMStorageAgent.Entry} payload | |
| */ | |
| addDOMStorage: function(payload) | |
| { | |
| this._model._addDOMStorage(new WebInspector.DOMStorage( | |
| payload.id, | |
| payload.origin, | |
| payload.isLocalStorage)); | |
| }, | |
| /** | |
| * @param {string} storageId | |
| */ | |
| domStorageUpdated: function(storageId) | |
| { | |
| this._model._domStorageUpdated(storageId); | |
| } | |
| } | |
| /** | |
| * @type {WebInspector.DOMStorageModel} | |
| */ | |
| WebInspector.domStorageModel = null; | |
| /* DataGrid.js */ | |
| /* | |
| * Copyright (C) 2008 Apple 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: | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. 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. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 | |
| * @extends {WebInspector.View} | |
| * @param {function(WebInspector.DataGridNode, number, string, string)=} editCallback | |
| * @param {function(WebInspector.DataGridNode)=} deleteCallback | |
| */ | |
| WebInspector.DataGrid = function(columns, editCallback, deleteCallback) | |
| { | |
| WebInspector.View.call(this); | |
| this.registerRequiredCSS("dataGrid.css"); | |
| this.element.className = "data-grid"; | |
| this.element.tabIndex = 0; | |
| this.element.addEventListener("keydown", this._keyDown.bind(this), false); | |
| this._headerTable = document.createElement("table"); | |
| this._headerTable.className = "header"; | |
| this._headerTableHeaders = {}; | |
| this._dataTable = document.createElement("table"); | |
| this._dataTable.className = "data"; | |
| this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true); | |
| this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true); | |
| this._dataTable.addEventListener("contextmenu", this._contextMenuInDataTable.bind(this), true); | |
| // FIXME: Add a createCallback which is different from editCallback and has different | |
| // behavior when creating a new node. | |
| if (editCallback) { | |
| this._dataTable.addEventListener("dblclick", this._ondblclick.bind(this), false); | |
| this._editCallback = editCallback; | |
| } | |
| if (deleteCallback) | |
| this._deleteCallback = deleteCallback; | |
| this.aligned = {}; | |
| this._scrollContainer = document.createElement("div"); | |
| this._scrollContainer.className = "data-container"; | |
| this._scrollContainer.appendChild(this._dataTable); | |
| this.element.appendChild(this._headerTable); | |
| this.element.appendChild(this._scrollContainer); | |
| var headerRow = document.createElement("tr"); | |
| var columnGroup = document.createElement("colgroup"); | |
| this._columnCount = 0; | |
| for (var columnIdentifier in columns) { | |
| var column = columns[columnIdentifier]; | |
| if (column.disclosure) | |
| this.disclosureColumnIdentifier = columnIdentifier; | |
| var col = document.createElement("col"); | |
| if (column.width) | |
| col.style.width = column.width; | |
| column.element = col; | |
| columnGroup.appendChild(col); | |
| var cell = document.createElement("th"); | |
| cell.className = columnIdentifier + "-column"; | |
| cell.columnIdentifier = columnIdentifier; | |
| this._headerTableHeaders[columnIdentifier] = cell; | |
| var div = document.createElement("div"); | |
| if (column.titleDOMFragment) | |
| div.appendChild(column.titleDOMFragment); | |
| else | |
| div.textContent = column.title; | |
| cell.appendChild(div); | |
| if (column.sort) { | |
| cell.addStyleClass("sort-" + column.sort); | |
| this._sortColumnCell = cell; | |
| } | |
| if (column.sortable) { | |
| cell.addEventListener("click", this._clickInHeaderCell.bind(this), false); | |
| cell.addStyleClass("sortable"); | |
| } | |
| if (column.aligned) | |
| this.aligned[columnIdentifier] = column.aligned; | |
| headerRow.appendChild(cell); | |
| ++this._columnCount; | |
| } | |
| columnGroup.span = this._columnCount; | |
| var cell = document.createElement("th"); | |
| cell.className = "corner"; | |
| headerRow.appendChild(cell); | |
| this._headerTableColumnGroup = columnGroup; | |
| this._headerTable.appendChild(this._headerTableColumnGroup); | |
| this.headerTableBody.appendChild(headerRow); | |
| var fillerRow = document.createElement("tr"); | |
| fillerRow.className = "filler"; | |
| for (var columnIdentifier in columns) { | |
| var column = columns[columnIdentifier]; | |
| var td = document.createElement("td"); | |
| td.className = columnIdentifier + "-column"; | |
| fillerRow.appendChild(td); | |
| } | |
| this._dataTableColumnGroup = columnGroup.cloneNode(true); | |
| this._dataTable.appendChild(this._dataTableColumnGroup); | |
| this.dataTableBody.appendChild(fillerRow); | |
| this.columns = columns || {}; | |
| this._columnsArray = []; | |
| for (var columnIdentifier in columns) { | |
| columns[columnIdentifier].ordinal = this._columnsArray.length; | |
| columns[columnIdentifier].identifier = columnIdentifier; | |
| this._columnsArray.push(columns[columnIdentifier]); | |
| } | |
| for (var i = 0; i < this._columnsArray.length; ++i) | |
| this._columnsArray[i].bodyElement = this._dataTableColumnGroup.children[i]; | |
| this.selectedNode = null; | |
| this.expandNodesWhenArrowing = false; | |
| this.setRootNode(new WebInspector.DataGridNode()); | |
| this.indentWidth = 15; | |
| this.resizers = []; | |
| this._columnWidthsInitialized = false; | |
| } | |
| WebInspector.DataGrid.Events = { | |
| SelectedNode: "SelectedNode", | |
| DeselectedNode: "DeselectedNode" | |
| } | |
| /** | |
| * @param {Array.<string>} columnNames | |
| * @param {Array.<string>} values | |
| */ | |
| WebInspector.DataGrid.createSortableDataGrid = function(columnNames, values) | |
| { | |
| var numColumns = columnNames.length; | |
| if (!numColumns) | |
| return null; | |
| var columns = {}; | |
| for (var i = 0; i < columnNames.length; ++i) { | |
| var column = {}; | |
| column.width = columnNames[i].length; | |
| column.title = columnNames[i]; | |
| column.sortable = true; | |
| columns[columnNames[i]] = column; | |
| } | |
| var nodes = []; | |
| for (var i = 0; i < values.length / numColumns; ++i) { | |
| var data = {}; | |
| for (var j = 0; j < columnNames.length; ++j) | |
| data[columnNames[j]] = values[numColumns * i + j]; | |
| var node = new WebInspector.DataGridNode(data, false); | |
| node.selectable = false; | |
| nodes.push(node); | |
| } | |
| var dataGrid = new WebInspector.DataGrid(columns); | |
| var length = nodes.length; | |
| for (var i = 0; i < length; ++i) | |
| dataGrid.rootNode().appendChild(nodes[i]); | |
| dataGrid.addEventListener("sorting changed", sortDataGrid, this); | |
| function sortDataGrid() | |
| { | |
| var nodes = dataGrid._rootNode.children.slice(); | |
| var sortColumnIdentifier = dataGrid.sortColumnIdentifier; | |
| var sortDirection = dataGrid.sortOrder === "ascending" ? 1 : -1; | |
| var columnIsNumeric = true; | |
| for (var i = 0; i < nodes.length; i++) { | |
| if (isNaN(Number(nodes[i].data[sortColumnIdentifier]))) | |
| columnIsNumeric = false; | |
| } | |
| function comparator(dataGridNode1, dataGridNode2) | |
| { | |
| var item1 = dataGridNode1.data[sortColumnIdentifier]; | |
| var item2 = dataGridNode2.data[sortColumnIdentifier]; | |
| var comparison; | |
| if (columnIsNumeric) { | |
| // Sort numbers based on comparing their values rather than a lexicographical comparison. | |
| var number1 = parseFloat(item1); | |
| var number2 = parseFloat(item2); | |
| comparison = number1 < number2 ? -1 : (number1 > number2 ? 1 : 0); | |
| } else | |
| comparison = item1 < item2 ? -1 : (item1 > item2 ? 1 : 0); | |
| return sortDirection * comparison; | |
| } | |
| nodes.sort(comparator); | |
| dataGrid.rootNode().removeChildren(); | |
| for (var i = 0; i < nodes.length; i++) | |
| dataGrid._rootNode.appendChild(nodes[i]); | |
| } | |
| return dataGrid; | |
| } | |
| WebInspector.DataGrid.prototype = { | |
| setRootNode: function(rootNode) | |
| { | |
| if (this._rootNode) { | |
| this._rootNode.removeChildren(); | |
| this._rootNode.dataGrid = null; | |
| this._rootNode._isRoot = false; | |
| } | |
| this._rootNode = rootNode; | |
| rootNode._isRoot = true; | |
| rootNode.hasChildren = false; | |
| rootNode._expanded = true; | |
| rootNode._revealed = true; | |
| rootNode.dataGrid = this; | |
| }, | |
| rootNode: function() | |
| { | |
| return this._rootNode; | |
| }, | |
| get refreshCallback() | |
| { | |
| return this._refreshCallback; | |
| }, | |
| set refreshCallback(refreshCallback) | |
| { | |
| this._refreshCallback = refreshCallback; | |
| }, | |
| _ondblclick: function(event) | |
| { | |
| if (this._editing || this._editingNode) | |
| return; | |
| this._startEditing(event.target); | |
| }, | |
| _startEditingColumnOfDataGridNode: function(node, column) | |
| { | |
| this._editing = true; | |
| this._editingNode = node; | |
| this._editingNode.select(); | |
| var element = this._editingNode._element.children[column]; | |
| WebInspector.startEditing(element, this._startEditingConfig(element)); | |
| window.getSelection().setBaseAndExtent(element, 0, element, 1); | |
| }, | |
| _startEditing: function(target) | |
| { | |
| var element = target.enclosingNodeOrSelfWithNodeName("td"); | |
| if (!element) | |
| return; | |
| this._editingNode = this.dataGridNodeFromNode(target); | |
| if (!this._editingNode) { | |
| if (!this.creationNode) | |
| return; | |
| this._editingNode = this.creationNode; | |
| } | |
| // Force editing the 1st column when editing the creation node | |
| if (this._editingNode.isCreationNode) | |
| return this._startEditingColumnOfDataGridNode(this._editingNode, 0); | |
| this._editing = true; | |
| WebInspector.startEditing(element, this._startEditingConfig(element)); | |
| window.getSelection().setBaseAndExtent(element, 0, element, 1); | |
| }, | |
| _startEditingConfig: function(element) | |
| { | |
| return new WebInspector.EditingConfig(this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); | |
| }, | |
| _editingCommitted: function(element, newText, oldText, context, moveDirection) | |
| { | |
| // FIXME: We need more column identifiers here throughout this function. | |
| // Not needed yet since only editable DataGrid is DOM Storage, which is Key - Value. | |
| // FIXME: Better way to do this than regular expressions? | |
| var columnIdentifier = parseInt(element.className.match(/\b(\d+)-column\b/)[1], 10); | |
| var textBeforeEditing = this._editingNode.data[columnIdentifier]; | |
| var currentEditingNode = this._editingNode; | |
| function moveToNextIfNeeded(wasChange) { | |
| if (!moveDirection) | |
| return; | |
| if (moveDirection === "forward") { | |
| if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange) | |
| return; | |
| if (columnIdentifier === 0) | |
| return this._startEditingColumnOfDataGridNode(currentEditingNode, 1); | |
| var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); | |
| if (nextDataGridNode) | |
| return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0); | |
| if (currentEditingNode.isCreationNode && wasChange) { | |
| this.addCreationNode(false); | |
| return this._startEditingColumnOfDataGridNode(this.creationNode, 0); | |
| } | |
| return; | |
| } | |
| if (moveDirection === "backward") { | |
| if (columnIdentifier === 1) | |
| return this._startEditingColumnOfDataGridNode(currentEditingNode, 0); | |
| var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true); | |
| if (nextDataGridNode) | |
| return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1); | |
| return; | |
| } | |
| } | |
| if (textBeforeEditing == newText) { | |
| this._editingCancelled(element); | |
| moveToNextIfNeeded.call(this, false); | |
| return; | |
| } | |
| // Update the text in the datagrid that we typed | |
| this._editingNode.data[columnIdentifier] = newText; | |
| // Make the callback - expects an editing node (table row), the column number that is being edited, | |
| // the text that used to be there, and the new text. | |
| this._editCallback(this._editingNode, columnIdentifier, textBeforeEditing, newText); | |
| if (this._editingNode.isCreationNode) | |
| this.addCreationNode(false); | |
| this._editingCancelled(element); | |
| moveToNextIfNeeded.call(this, true); | |
| }, | |
| _editingCancelled: function(element) | |
| { | |
| delete this._editing; | |
| this._editingNode = null; | |
| }, | |
| /** | |
| * @return {?string} | |
| */ | |
| get sortColumnIdentifier() | |
| { | |
| if (!this._sortColumnCell) | |
| return null; | |
| return this._sortColumnCell.columnIdentifier; | |
| }, | |
| /** | |
| * @return {?string} | |
| */ | |
| get sortOrder() | |
| { | |
| if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending")) | |
| return "ascending"; | |
| if (this._sortColumnCell.hasStyleClass("sort-descending")) | |
| return "descending"; | |
| return null; | |
| }, | |
| get headerTableBody() | |
| { | |
| if ("_headerTableBody" in this) | |
| return this._headerTableBody; | |
| this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0]; | |
| if (!this._headerTableBody) { | |
| this._headerTableBody = this.element.ownerDocument.createElement("tbody"); | |
| this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot); | |
| } | |
| return this._headerTableBody; | |
| }, | |
| get dataTableBody() | |
| { | |
| if ("_dataTableBody" in this) | |
| return this._dataTableBody; | |
| this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0]; | |
| if (!this._dataTableBody) { | |
| this._dataTableBody = this.element.ownerDocument.createElement("tbody"); | |
| this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot); | |
| } | |
| return this._dataTableBody; | |
| }, | |
| /** | |
| * @param {number=} maxDescentLevel | |
| */ | |
| autoSizeColumns: function(minPercent, maxPercent, maxDescentLevel) | |
| { | |
| if (minPercent) | |
| minPercent = Math.min(minPercent, Math.floor(100 / this._columnCount)); | |
| var widths = {}; | |
| var columns = this.columns; | |
| for (var columnIdentifier in columns) | |
| widths[columnIdentifier] = (columns[columnIdentifier].title || "").length; | |
| maxDescentLevel = maxDescentLevel || 0; | |
| var children = this._enumerateChildren(this._rootNode, [], maxDescentLevel + 1); | |
| for (var i = 0; i < children.length; ++i) { | |
| var node = children[i]; | |
| for (var columnIdentifier in columns) { | |
| var text = node.data[columnIdentifier] || ""; | |
| if (text.length > widths[columnIdentifier]) | |
| widths[columnIdentifier] = text.length; | |
| } | |
| } | |
| var totalColumnWidths = 0; | |
| for (var columnIdentifier in columns) | |
| totalColumnWidths += widths[columnIdentifier]; | |
| var recoupPercent = 0; | |
| for (var columnIdentifier in columns) { | |
| var width = Math.round(100 * widths[columnIdentifier] / totalColumnWidths); | |
| if (minPercent && width < minPercent) { | |
| recoupPercent += (minPercent - width); | |
| width = minPercent; | |
| } else if (maxPercent && width > maxPercent) { | |
| recoupPercent -= (width - maxPercent); | |
| width = maxPercent; | |
| } | |
| widths[columnIdentifier] = width; | |
| } | |
| while (minPercent && recoupPercent > 0) { | |
| for (var columnIdentifier in columns) { | |
| if (widths[columnIdentifier] > minPercent) { | |
| --widths[columnIdentifier]; | |
| --recoupPercent; | |
| if (!recoupPercent) | |
| break; | |
| } | |
| } | |
| } | |
| while (maxPercent && recoupPercent < 0) { | |
| for (var columnIdentifier in columns) { | |
| if (widths[columnIdentifier] < maxPercent) { | |
| ++widths[columnIdentifier]; | |
| ++recoupPercent; | |
| if (!recoupPercent) | |
| break; | |
| } | |
| } | |
| } | |
| for (var columnIdentifier in columns) | |
| columns[columnIdentifier].element.style.width = widths[columnIdentifier] + "%"; | |
| this._columnWidthsInitialized = false; | |
| this.updateWidths(); | |
| }, | |
| _enumerateChildren: function(rootNode, result, maxLevel) | |
| { | |
| if (!rootNode._isRoot) | |
| result.push(rootNode); | |
| if (!maxLevel) | |
| return; | |
| for (var i = 0; i < rootNode.children.length; ++i) | |
| this._enumerateChildren(rootNode.children[i], result, maxLevel - 1); | |
| return result; | |
| }, | |
| onResize: function() | |
| { | |
| this.updateWidths(); | |
| }, | |
| // Updates the widths of the table, including the positions of the column | |
| // resizers. | |
| // | |
| // IMPORTANT: This function MUST be called once after the element of the | |
| // DataGrid is attached to its parent element and every subsequent time the | |
| // width of the parent element is changed in order to make it possible to | |
| // resize the columns. | |
| // | |
| // If this function is not called after the DataGrid is attached to its | |
| // parent element, then the DataGrid's columns will not be resizable. | |
| updateWidths: function() | |
| { | |
| var headerTableColumns = this._headerTableColumnGroup.children; | |
| var tableWidth = this._dataTable.offsetWidth; | |
| var numColumns = headerTableColumns.length; | |
| if (!this._columnWidthsInitialized && this.element.offsetWidth) { | |
| for (var i = 0; i < numColumns; i++) { | |
| var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth; | |
| var percentWidth = ((columnWidth / tableWidth) * 100) + "%"; | |
| this._headerTableColumnGroup.children[i].style.width = percentWidth; | |
| this._dataTableColumnGroup.children[i].style.width = percentWidth; | |
| } | |
| this._columnWidthsInitialized = true; | |
| } | |
| this._positionResizers(); | |
| this.dispatchEventToListeners("width changed"); | |
| }, | |
| columnWidthsMap: function() | |
| { | |
| var result = {}; | |
| for (var i = 0; i < this._columnsArray.length; ++i) { | |
| var width = this._headerTableColumnGroup.children[i].style.width; | |
| result[this._columnsArray[i].columnIdentifier] = parseFloat(width); | |
| } | |
| return result; | |
| }, | |
| applyColumnWidthsMap: function(columnWidthsMap) | |
| { | |
| for (var columnIdentifier in this.columns) { | |
| var column = this.columns[columnIdentifier]; | |
| var width = (columnWidthsMap[columnIdentifier] || 0) + "%"; | |
| this._headerTableColumnGroup.children[column.ordinal].style.width = width; | |
| this._dataTableColumnGroup.children[column.ordinal].style.width = width; | |
| } | |
| delete this._columnWidthsInitialized; | |
| this.updateWidths(); | |
| }, | |
| isColumnVisible: function(columnIdentifier) | |
| { | |
| var column = this.columns[columnIdentifier]; | |
| var columnElement = column.element; | |
| return !columnElement.hidden; | |
| }, | |
| showColumn: function(columnIdentifier) | |
| { | |
| var column = this.columns[columnIdentifier]; | |
| var columnElement = column.element; | |
| if (!columnElement.hidden) | |
| return; | |
| columnElement.hidden = false; | |
| columnElement.removeStyleClass("hidden"); | |
| var columnBodyElement = column.bodyElement; | |
| columnBodyElement.hidden = false; | |
| columnBodyElement.removeStyleClass("hidden"); | |
| }, | |
| hideColumn: function(columnIdentifier) | |
| { | |
| var column = this.columns[columnIdentifier]; | |
| var columnElement = column.element; | |
| if (columnElement.hidden) | |
| return; | |
| var oldWidth = parseFloat(columnElement.style.width); | |
| columnElement.hidden = true; | |
| columnElement.addStyleClass("hidden"); | |
| columnElement.style.width = 0; | |
| var columnBodyElement = column.bodyElement; | |
| columnBodyElement.hidden = true; | |
| columnBodyElement.addStyleClass("hidden"); | |
| columnBodyElement.style.width = 0; | |
| this._columnWidthsInitialized = false; | |
| }, | |
| get scrollContainer() | |
| { | |
| return this._scrollContainer; | |
| }, | |
| isScrolledToLastRow: function() | |
| { | |
| return this._scrollContainer.isScrolledToBottom(); | |
| }, | |
| scrollToLastRow: function() | |
| { | |
| this._scrollContainer.scrollTop = this._scrollContainer.scrollHeight - this._scrollContainer.offsetHeight; | |
| }, | |
| _positionResizers: function() | |
| { | |
| var headerTableColumns = this._headerTableColumnGroup.children; | |
| var numColumns = headerTableColumns.length; | |
| var left = 0; | |
| var previousResizer = null; | |
| for (var i = 0; i < numColumns - 1; i++) { | |
| var resizer = this.resizers[i]; | |
| if (!resizer) { | |
| resizer = document.createElement("div"); | |
| resizer.addStyleClass("data-grid-resizer"); | |
| WebInspector.installDragHandle(resizer, this._startResizerDragging.bind(this), this._resizerDragging.bind(this), this._endResizerDragging.bind(this), "col-resize"); | |
| this.element.appendChild(resizer); | |
| this.resizers[i] = resizer; | |
| } | |
| left += this.headerTableBody.rows[0].cells[i].offsetWidth; | |
| var columnIsVisible = !this._headerTableColumnGroup.children[i].hidden; | |
| if (columnIsVisible) { | |
| resizer.style.removeProperty("display"); | |
| resizer.style.left = left + "px"; | |
| resizer.leftNeighboringColumnID = i; | |
| if (previousResizer) | |
| previousResizer.rightNeighboringColumnID = i; | |
| previousResizer = resizer; | |
| } else { | |
| resizer.style.setProperty("display", "none"); | |
| resizer.leftNeighboringColumnID = 0; | |
| resizer.rightNeighboringColumnID = 0; | |
| } | |
| } | |
| if (previousResizer) | |
| previousResizer.rightNeighboringColumnID = numColumns - 1; | |
| }, | |
| addCreationNode: function(hasChildren) | |
| { | |
| if (this.creationNode) | |
| this.creationNode.makeNormal(); | |
| var emptyData = {}; | |
| for (var column in this.columns) | |
| emptyData[column] = ''; | |
| this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren); | |
| this.rootNode().appendChild(this.creationNode); | |
| }, | |
| sortNodes: function(comparator, reverseMode) | |
| { | |
| function comparatorWrapper(a, b) | |
| { | |
| if (a._dataGridNode._data.summaryRow) | |
| return 1; | |
| if (b._dataGridNode._data.summaryRow) | |
| return -1; | |
| var aDataGirdNode = a._dataGridNode; | |
| var bDataGirdNode = b._dataGridNode; | |
| return reverseMode ? comparator(bDataGirdNode, aDataGirdNode) : comparator(aDataGirdNode, bDataGirdNode); | |
| } | |
| var tbody = this.dataTableBody; | |
| var tbodyParent = tbody.parentElement; | |
| tbodyParent.removeChild(tbody); | |
| var childNodes = tbody.childNodes; | |
| var fillerRow = childNodes[childNodes.length - 1]; | |
| var sortedRows = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1); | |
| sortedRows.sort(comparatorWrapper); | |
| var sortedRowsLength = sortedRows.length; | |
| tbody.removeChildren(); | |
| var previousSiblingNode = null; | |
| for (var i = 0; i < sortedRowsLength; ++i) { | |
| var row = sortedRows[i]; | |
| var node = row._dataGridNode; | |
| node.previousSibling = previousSiblingNode; | |
| if (previousSiblingNode) | |
| previousSiblingNode.nextSibling = node; | |
| tbody.appendChild(row); | |
| previousSiblingNode = node; | |
| } | |
| if (previousSiblingNode) | |
| previousSiblingNode.nextSibling = null; | |
| tbody.appendChild(fillerRow); | |
| tbodyParent.appendChild(tbody); | |
| }, | |
| _keyDown: function(event) | |
| { | |
| if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing) | |
| return; | |
| var handled = false; | |
| var nextSelectedNode; | |
| if (event.keyIdentifier === "Up" && !event.altKey) { | |
| nextSelectedNode = this.selectedNode.traversePreviousNode(true); | |
| while (nextSelectedNode && !nextSelectedNode.selectable) | |
| nextSelectedNode = nextSelectedNode.traversePreviousNode(true); | |
| handled = nextSelectedNode ? true : false; | |
| } else if (event.keyIdentifier === "Down" && !event.altKey) { | |
| nextSelectedNode = this.selectedNode.traverseNextNode(true); | |
| while (nextSelectedNode && !nextSelectedNode.selectable) | |
| nextSelectedNode = nextSelectedNode.traverseNextNode(true); | |
| handled = nextSelectedNode ? true : false; | |
| } else if (event.keyIdentifier === "Left") { | |
| if (this.selectedNode.expanded) { | |
| if (event.altKey) | |
| this.selectedNode.collapseRecursively(); | |
| else | |
| this.selectedNode.collapse(); | |
| handled = true; | |
| } else if (this.selectedNode.parent && !this.selectedNode.parent._isRoot) { | |
| handled = true; | |
| if (this.selectedNode.parent.selectable) { | |
| nextSelectedNode = this.selectedNode.parent; | |
| handled = nextSelectedNode ? true : false; | |
| } else if (this.selectedNode.parent) | |
| this.selectedNode.parent.collapse(); | |
| } | |
| } else if (event.keyIdentifier === "Right") { | |
| if (!this.selectedNode.revealed) { | |
| this.selectedNode.reveal(); | |
| handled = true; | |
| } else if (this.selectedNode.hasChildren) { | |
| handled = true; | |
| if (this.selectedNode.expanded) { | |
| nextSelectedNode = this.selectedNode.children[0]; | |
| handled = nextSelectedNode ? true : false; | |
| } else { | |
| if (event.altKey) | |
| this.selectedNode.expandRecursively(); | |
| else | |
| this.selectedNode.expand(); | |
| } | |
| } | |
| } else if (event.keyCode === 8 || event.keyCode === 46) { | |
| if (this._deleteCallback) { | |
| handled = true; | |
| this._deleteCallback(this.selectedNode); | |
| } | |
| } else if (isEnterKey(event)) { | |
| if (this._editCallback) { | |
| handled = true; | |
| this._startEditing(this.selectedNode._element.children[0]); | |
| } | |
| } | |
| if (nextSelectedNode) { | |
| nextSelectedNode.reveal(); | |
| nextSelectedNode.select(); | |
| } | |
| if (handled) | |
| event.consume(true); | |
| }, | |
| dataGridNodeFromNode: function(target) | |
| { | |
| var rowElement = target.enclosingNodeOrSelfWithNodeName("tr"); | |
| return rowElement && rowElement._dataGridNode; | |
| }, | |
| dataGridNodeFromPoint: function(x, y) | |
| { | |
| var node = this._dataTable.ownerDocument.elementFromPoint(x, y); | |
| var rowElement = node.enclosingNodeOrSelfWithNodeName("tr"); | |
| return rowElement && rowElement._dataGridNode; | |
| }, | |
| _clickInHeaderCell: function(event) | |
| { | |
| var cell = event.target.enclosingNodeOrSelfWithNodeName("th"); | |
| if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable")) | |
| return; | |
| var sortOrder = this.sortOrder; | |
| if (this._sortColumnCell) | |
| this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+"); | |
| if (cell == this._sortColumnCell) { | |
| if (sortOrder === "ascending") | |
| sortOrder = "descending"; | |
| else | |
| sortOrder = "ascending"; | |
| } | |
| this._sortColumnCell = cell; | |
| cell.addStyleClass("sort-" + sortOrder); | |
| this.dispatchEventToListeners("sorting changed"); | |
| }, | |
| markColumnAsSortedBy: function(columnIdentifier, sortOrder) | |
| { | |
| if (this._sortColumnCell) | |
| this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+"); | |
| this._sortColumnCell = this._headerTableHeaders[columnIdentifier]; | |
| this._sortColumnCell.addStyleClass("sort-" + sortOrder); | |
| }, | |
| headerTableHeader: function(columnIdentifier) | |
| { | |
| return this._headerTableHeaders[columnIdentifier]; | |
| }, | |
| _mouseDownInDataTable: function(event) | |
| { | |
| var gridNode = this.dataGridNodeFromNode(event.target); | |
| if (!gridNode || !gridNode.selectable) | |
| return; | |
| if (gridNode.isEventWithinDisclosureTriangle(event)) | |
| return; | |
| if (event.metaKey) { | |
| if (gridNode.selected) | |
| gridNode.deselect(); | |
| else | |
| gridNode.select(); | |
| } else | |
| gridNode.select(); | |
| }, | |
| _contextMenuInDataTable: function(event) | |
| { | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| var gridNode = this.dataGridNodeFromNode(event.target); | |
| if (this._refreshCallback && (!gridNode || gridNode !== this.creationNode)) | |
| contextMenu.appendItem(WebInspector.UIString("Refresh"), this._refreshCallback.bind(this)); | |
| if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) { | |
| if (this._editCallback) { | |
| if (gridNode === this.creationNode) | |
| contextMenu.appendItem(WebInspector.UIString("Add New"), this._startEditing.bind(this, event.target)); | |
| else | |
| contextMenu.appendItem(WebInspector.UIString("Edit"), this._startEditing.bind(this, event.target)); | |
| } | |
| if (this._deleteCallback && gridNode !== this.creationNode) | |
| contextMenu.appendItem(WebInspector.UIString("Delete"), this._deleteCallback.bind(this, gridNode)); | |
| } | |
| contextMenu.show(event); | |
| }, | |
| _clickInDataTable: function(event) | |
| { | |
| var gridNode = this.dataGridNodeFromNode(event.target); | |
| if (!gridNode || !gridNode.hasChildren) | |
| return; | |
| if (!gridNode.isEventWithinDisclosureTriangle(event)) | |
| return; | |
| if (gridNode.expanded) { | |
| if (event.altKey) | |
| gridNode.collapseRecursively(); | |
| else | |
| gridNode.collapse(); | |
| } else { | |
| if (event.altKey) | |
| gridNode.expandRecursively(); | |
| else | |
| gridNode.expand(); | |
| } | |
| }, | |
| get resizeMethod() | |
| { | |
| if (typeof this._resizeMethod === "undefined") | |
| return WebInspector.DataGrid.ResizeMethod.Nearest; | |
| return this._resizeMethod; | |
| }, | |
| set resizeMethod(method) | |
| { | |
| this._resizeMethod = method; | |
| }, | |
| _startResizerDragging: function(event) | |
| { | |
| this._currentResizer = event.target; | |
| return !!this._currentResizer.rightNeighboringColumnID | |
| }, | |
| _resizerDragging: function(event) | |
| { | |
| var resizer = this._currentResizer; | |
| if (!resizer) | |
| return; | |
| var dragPoint = event.clientX - this.element.totalOffsetLeft(); | |
| var leftCellIndex = resizer.leftNeighboringColumnID; | |
| var rightCellIndex = resizer.rightNeighboringColumnID; | |
| var firstRowCells = this.headerTableBody.rows[0].cells; | |
| var leftEdgeOfPreviousColumn = 0; | |
| for (var i = 0; i < leftCellIndex; i++) | |
| leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth; | |
| if (this.resizeMethod == WebInspector.DataGrid.ResizeMethod.Last) { | |
| rightCellIndex = this.resizers.length; | |
| } else if (this.resizeMethod == WebInspector.DataGrid.ResizeMethod.First) { | |
| leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth; | |
| leftCellIndex = 0; | |
| } | |
| var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[leftCellIndex].offsetWidth + firstRowCells[rightCellIndex].offsetWidth; | |
| var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding; | |
| var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding; | |
| dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum); | |
| resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px"; | |
| var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%"; | |
| this._headerTableColumnGroup.children[leftCellIndex].style.width = percentLeftColumn; | |
| this._dataTableColumnGroup.children[leftCellIndex].style.width = percentLeftColumn; | |
| var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%"; | |
| this._headerTableColumnGroup.children[rightCellIndex].style.width = percentRightColumn; | |
| this._dataTableColumnGroup.children[rightCellIndex].style.width = percentRightColumn; | |
| this._positionResizers(); | |
| event.preventDefault(); | |
| this.dispatchEventToListeners("width changed"); | |
| }, | |
| _endResizerDragging: function(event) | |
| { | |
| this._currentResizer = null; | |
| this.dispatchEventToListeners("width changed"); | |
| }, | |
| ColumnResizePadding: 10, | |
| CenterResizerOverBorderAdjustment: 3, | |
| } | |
| WebInspector.DataGrid.ResizeMethod = { | |
| Nearest: "nearest", | |
| First: "first", | |
| Last: "last" | |
| } | |
| WebInspector.DataGrid.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.DataGridNode = function(data, hasChildren) | |
| { | |
| this._expanded = false; | |
| this._selected = false; | |
| this._shouldRefreshChildren = true; | |
| this._data = data || {}; | |
| this.hasChildren = hasChildren || false; | |
| this.children = []; | |
| this.dataGrid = null; | |
| this.parent = null; | |
| this.previousSibling = null; | |
| this.nextSibling = null; | |
| this.disclosureToggleWidth = 10; | |
| } | |
| WebInspector.DataGridNode.prototype = { | |
| selectable: true, | |
| _isRoot: false, | |
| get element() | |
| { | |
| if (this._element) | |
| return this._element; | |
| if (!this.dataGrid) | |
| return null; | |
| this._element = document.createElement("tr"); | |
| this._element._dataGridNode = this; | |
| if (this.hasChildren) | |
| this._element.addStyleClass("parent"); | |
| if (this.expanded) | |
| this._element.addStyleClass("expanded"); | |
| if (this.selected) | |
| this._element.addStyleClass("selected"); | |
| if (this.revealed) | |
| this._element.addStyleClass("revealed"); | |
| this.createCells(); | |
| return this._element; | |
| }, | |
| createCells: function() | |
| { | |
| for (var columnIdentifier in this.dataGrid.columns) { | |
| var cell = this.createCell(columnIdentifier); | |
| this._element.appendChild(cell); | |
| } | |
| }, | |
| get data() | |
| { | |
| return this._data; | |
| }, | |
| set data(x) | |
| { | |
| this._data = x || {}; | |
| this.refresh(); | |
| }, | |
| get revealed() | |
| { | |
| if ("_revealed" in this) | |
| return this._revealed; | |
| var currentAncestor = this.parent; | |
| while (currentAncestor && !currentAncestor._isRoot) { | |
| if (!currentAncestor.expanded) { | |
| this._revealed = false; | |
| return false; | |
| } | |
| currentAncestor = currentAncestor.parent; | |
| } | |
| this._revealed = true; | |
| return true; | |
| }, | |
| set hasChildren(x) | |
| { | |
| if (this._hasChildren === x) | |
| return; | |
| this._hasChildren = x; | |
| if (!this._element) | |
| return; | |
| if (this._hasChildren) | |
| { | |
| this._element.addStyleClass("parent"); | |
| if (this.expanded) | |
| this._element.addStyleClass("expanded"); | |
| } | |
| else | |
| { | |
| this._element.removeStyleClass("parent"); | |
| this._element.removeStyleClass("expanded"); | |
| } | |
| }, | |
| get hasChildren() | |
| { | |
| return this._hasChildren; | |
| }, | |
| set revealed(x) | |
| { | |
| if (this._revealed === x) | |
| return; | |
| this._revealed = x; | |
| if (this._element) { | |
| if (this._revealed) | |
| this._element.addStyleClass("revealed"); | |
| else | |
| this._element.removeStyleClass("revealed"); | |
| } | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i].revealed = x && this.expanded; | |
| }, | |
| get depth() | |
| { | |
| if ("_depth" in this) | |
| return this._depth; | |
| if (this.parent && !this.parent._isRoot) | |
| this._depth = this.parent.depth + 1; | |
| else | |
| this._depth = 0; | |
| return this._depth; | |
| }, | |
| get leftPadding() | |
| { | |
| if (typeof(this._leftPadding) === "number") | |
| return this._leftPadding; | |
| this._leftPadding = this.depth * this.dataGrid.indentWidth; | |
| return this._leftPadding; | |
| }, | |
| get shouldRefreshChildren() | |
| { | |
| return this._shouldRefreshChildren; | |
| }, | |
| set shouldRefreshChildren(x) | |
| { | |
| this._shouldRefreshChildren = x; | |
| if (x && this.expanded) | |
| this.expand(); | |
| }, | |
| get selected() | |
| { | |
| return this._selected; | |
| }, | |
| set selected(x) | |
| { | |
| if (x) | |
| this.select(); | |
| else | |
| this.deselect(); | |
| }, | |
| get expanded() | |
| { | |
| return this._expanded; | |
| }, | |
| set expanded(x) | |
| { | |
| if (x) | |
| this.expand(); | |
| else | |
| this.collapse(); | |
| }, | |
| refresh: function() | |
| { | |
| if (!this._element || !this.dataGrid) | |
| return; | |
| this._element.removeChildren(); | |
| this.createCells(); | |
| }, | |
| createCell: function(columnIdentifier) | |
| { | |
| var cell = document.createElement("td"); | |
| cell.className = columnIdentifier + "-column"; | |
| var alignment = this.dataGrid.aligned[columnIdentifier]; | |
| if (alignment) | |
| cell.addStyleClass(alignment); | |
| var div = document.createElement("div"); | |
| div.textContent = this.data[columnIdentifier]; | |
| cell.appendChild(div); | |
| if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) { | |
| cell.addStyleClass("disclosure"); | |
| if (this.leftPadding) | |
| cell.style.setProperty("padding-left", this.leftPadding + "px"); | |
| } | |
| return cell; | |
| }, | |
| nodeHeight: function() | |
| { | |
| var rowHeight = 16; | |
| if (!this.revealed) | |
| return 0; | |
| if (!this.expanded) | |
| return rowHeight; | |
| var result = rowHeight; | |
| for (var i = 0; i < this.children.length; i++) | |
| result += this.children[i].nodeHeight(); | |
| return result; | |
| }, | |
| appendChild: function(child) | |
| { | |
| this.insertChild(child, this.children.length); | |
| }, | |
| insertChild: function(child, index) | |
| { | |
| if (!child) | |
| throw("insertChild: Node can't be undefined or null."); | |
| if (child.parent === this) | |
| throw("insertChild: Node is already a child of this node."); | |
| if (child.parent) | |
| child.parent.removeChild(child); | |
| this.children.splice(index, 0, child); | |
| this.hasChildren = true; | |
| child.parent = this; | |
| child.dataGrid = this.dataGrid; | |
| child._recalculateSiblings(index); | |
| delete child._depth; | |
| delete child._revealed; | |
| delete child._attached; | |
| child._shouldRefreshChildren = true; | |
| var current = child.children[0]; | |
| while (current) { | |
| current.dataGrid = this.dataGrid; | |
| delete current._depth; | |
| delete current._revealed; | |
| delete current._attached; | |
| current._shouldRefreshChildren = true; | |
| current = current.traverseNextNode(false, child, true); | |
| } | |
| if (this.expanded) | |
| child._attach(); | |
| if (!this.revealed) | |
| child.revealed = false; | |
| }, | |
| removeChild: function(child) | |
| { | |
| if (!child) | |
| throw("removeChild: Node can't be undefined or null."); | |
| if (child.parent !== this) | |
| throw("removeChild: Node is not a child of this node."); | |
| child.deselect(); | |
| child._detach(); | |
| this.children.remove(child, true); | |
| if (child.previousSibling) | |
| child.previousSibling.nextSibling = child.nextSibling; | |
| if (child.nextSibling) | |
| child.nextSibling.previousSibling = child.previousSibling; | |
| child.dataGrid = null; | |
| child.parent = null; | |
| child.nextSibling = null; | |
| child.previousSibling = null; | |
| if (this.children.length <= 0) | |
| this.hasChildren = false; | |
| }, | |
| removeChildren: function() | |
| { | |
| for (var i = 0; i < this.children.length; ++i) { | |
| var child = this.children[i]; | |
| child.deselect(); | |
| child._detach(); | |
| child.dataGrid = null; | |
| child.parent = null; | |
| child.nextSibling = null; | |
| child.previousSibling = null; | |
| } | |
| this.children = []; | |
| this.hasChildren = false; | |
| }, | |
| _recalculateSiblings: function(myIndex) | |
| { | |
| if (!this.parent) | |
| return; | |
| var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null); | |
| if (previousChild) { | |
| previousChild.nextSibling = this; | |
| this.previousSibling = previousChild; | |
| } else | |
| this.previousSibling = null; | |
| var nextChild = this.parent.children[myIndex + 1]; | |
| if (nextChild) { | |
| nextChild.previousSibling = this; | |
| this.nextSibling = nextChild; | |
| } else | |
| this.nextSibling = null; | |
| }, | |
| collapse: function() | |
| { | |
| if (this._isRoot) | |
| return; | |
| if (this._element) | |
| this._element.removeStyleClass("expanded"); | |
| this._expanded = false; | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i].revealed = false; | |
| this.dispatchEventToListeners("collapsed"); | |
| }, | |
| collapseRecursively: function() | |
| { | |
| var item = this; | |
| while (item) { | |
| if (item.expanded) | |
| item.collapse(); | |
| item = item.traverseNextNode(false, this, true); | |
| } | |
| }, | |
| expand: function() | |
| { | |
| if (!this.hasChildren || this.expanded) | |
| return; | |
| if (this._isRoot) | |
| return; | |
| if (this.revealed && !this._shouldRefreshChildren) | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i].revealed = true; | |
| if (this._shouldRefreshChildren) { | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i]._detach(); | |
| this.dispatchEventToListeners("populate"); | |
| if (this._attached) { | |
| for (var i = 0; i < this.children.length; ++i) { | |
| var child = this.children[i]; | |
| if (this.revealed) | |
| child.revealed = true; | |
| child._attach(); | |
| } | |
| } | |
| delete this._shouldRefreshChildren; | |
| } | |
| if (this._element) | |
| this._element.addStyleClass("expanded"); | |
| this._expanded = true; | |
| this.dispatchEventToListeners("expanded"); | |
| }, | |
| expandRecursively: function() | |
| { | |
| var item = this; | |
| while (item) { | |
| item.expand(); | |
| item = item.traverseNextNode(false, this); | |
| } | |
| }, | |
| reveal: function() | |
| { | |
| if (this._isRoot) | |
| return; | |
| var currentAncestor = this.parent; | |
| while (currentAncestor && !currentAncestor._isRoot) { | |
| if (!currentAncestor.expanded) | |
| currentAncestor.expand(); | |
| currentAncestor = currentAncestor.parent; | |
| } | |
| this.element.scrollIntoViewIfNeeded(false); | |
| this.dispatchEventToListeners("revealed"); | |
| }, | |
| select: function(supressSelectedEvent) | |
| { | |
| if (!this.dataGrid || !this.selectable || this.selected) | |
| return; | |
| if (this.dataGrid.selectedNode) | |
| this.dataGrid.selectedNode.deselect(); | |
| this._selected = true; | |
| this.dataGrid.selectedNode = this; | |
| if (this._element) | |
| this._element.addStyleClass("selected"); | |
| if (!supressSelectedEvent) { | |
| this.dispatchEventToListeners("selected"); | |
| this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.SelectedNode); | |
| } | |
| }, | |
| revealAndSelect: function() | |
| { | |
| if (this._isRoot) | |
| return; | |
| this.reveal(); | |
| this.select(); | |
| }, | |
| deselect: function(supressDeselectedEvent) | |
| { | |
| if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected) | |
| return; | |
| this._selected = false; | |
| this.dataGrid.selectedNode = null; | |
| if (this._element) | |
| this._element.removeStyleClass("selected"); | |
| if (!supressDeselectedEvent) { | |
| this.dispatchEventToListeners("deselected"); | |
| this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.DeselectedNode); | |
| } | |
| }, | |
| traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info) | |
| { | |
| if (!dontPopulate && this.hasChildren) | |
| this.dispatchEventToListeners("populate"); | |
| if (info) | |
| info.depthChange = 0; | |
| var node = (!skipHidden || this.revealed) ? this.children[0] : null; | |
| if (node && (!skipHidden || this.expanded)) { | |
| if (info) | |
| info.depthChange = 1; | |
| return node; | |
| } | |
| if (this === stayWithin) | |
| return null; | |
| node = (!skipHidden || this.revealed) ? this.nextSibling : null; | |
| if (node) | |
| return node; | |
| node = this; | |
| while (node && !node._isRoot && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) { | |
| if (info) | |
| info.depthChange -= 1; | |
| node = node.parent; | |
| } | |
| if (!node) | |
| return null; | |
| return (!skipHidden || node.revealed) ? node.nextSibling : null; | |
| }, | |
| traversePreviousNode: function(skipHidden, dontPopulate) | |
| { | |
| var node = (!skipHidden || this.revealed) ? this.previousSibling : null; | |
| if (!dontPopulate && node && node.hasChildren) | |
| node.dispatchEventToListeners("populate"); | |
| while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) { | |
| if (!dontPopulate && node.hasChildren) | |
| node.dispatchEventToListeners("populate"); | |
| node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null); | |
| } | |
| if (node) | |
| return node; | |
| if (!this.parent || this.parent._isRoot) | |
| return null; | |
| return this.parent; | |
| }, | |
| isEventWithinDisclosureTriangle: function(event) | |
| { | |
| if (!this.hasChildren) | |
| return false; | |
| var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); | |
| if (!cell.hasStyleClass("disclosure")) | |
| return false; | |
| var left = cell.totalOffsetLeft() + this.leftPadding; | |
| return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth; | |
| }, | |
| _attach: function() | |
| { | |
| if (!this.dataGrid || this._attached) | |
| return; | |
| this._attached = true; | |
| var nextNode = null; | |
| var previousNode = this.traversePreviousNode(true, true); | |
| if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling) | |
| nextNode = previousNode.element.nextSibling; | |
| if (!nextNode) | |
| nextNode = this.dataGrid.dataTableBody.firstChild; | |
| this.dataGrid.dataTableBody.insertBefore(this.element, nextNode); | |
| if (this.expanded) | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i]._attach(); | |
| }, | |
| _detach: function() | |
| { | |
| if (!this._attached) | |
| return; | |
| this._attached = false; | |
| if (this._element && this._element.parentNode) | |
| this._element.parentNode.removeChild(this._element); | |
| for (var i = 0; i < this.children.length; ++i) | |
| this.children[i]._detach(); | |
| this.wasDetached(); | |
| }, | |
| wasDetached: function() | |
| { | |
| }, | |
| savePosition: function() | |
| { | |
| if (this._savedPosition) | |
| return; | |
| if (!this.parent) | |
| throw("savePosition: Node must have a parent."); | |
| this._savedPosition = { | |
| parent: this.parent, | |
| index: this.parent.children.indexOf(this) | |
| }; | |
| }, | |
| restorePosition: function() | |
| { | |
| if (!this._savedPosition) | |
| return; | |
| if (this.parent !== this._savedPosition.parent) | |
| this._savedPosition.parent.insertChild(this, this._savedPosition.index); | |
| delete this._savedPosition; | |
| } | |
| } | |
| WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.CreationDataGridNode = function(data, hasChildren) | |
| { | |
| WebInspector.DataGridNode.call(this, data, hasChildren); | |
| this.isCreationNode = true; | |
| } | |
| WebInspector.CreationDataGridNode.prototype = { | |
| makeNormal: function() | |
| { | |
| delete this.isCreationNode; | |
| delete this.makeNormal; | |
| } | |
| } | |
| WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; | |
| WebInspector.ShowMoreDataGridNode = function(callback, startPosition, endPosition, chunkSize) | |
| { | |
| WebInspector.DataGridNode.call(this, {summaryRow:true}, false); | |
| this._callback = callback; | |
| this._startPosition = startPosition; | |
| this._endPosition = endPosition; | |
| this._chunkSize = chunkSize; | |
| this.showNext = document.createElement("button"); | |
| this.showNext.setAttribute("type", "button"); | |
| this.showNext.addEventListener("click", this._showNextChunk.bind(this), false); | |
| this.showNext.textContent = WebInspector.UIString("Show %d before", this._chunkSize); | |
| this.showAll = document.createElement("button"); | |
| this.showAll.setAttribute("type", "button"); | |
| this.showAll.addEventListener("click", this._showAll.bind(this), false); | |
| this.showLast = document.createElement("button"); | |
| this.showLast.setAttribute("type", "button"); | |
| this.showLast.addEventListener("click", this._showLastChunk.bind(this), false); | |
| this.showLast.textContent = WebInspector.UIString("Show %d after", this._chunkSize); | |
| this._updateLabels(); | |
| this.selectable = false; | |
| } | |
| WebInspector.ShowMoreDataGridNode.prototype = { | |
| _showNextChunk: function() | |
| { | |
| this._callback(this._startPosition, this._startPosition + this._chunkSize); | |
| }, | |
| _showAll: function() | |
| { | |
| this._callback(this._startPosition, this._endPosition); | |
| }, | |
| _showLastChunk: function() | |
| { | |
| this._callback(this._endPosition - this._chunkSize, this._endPosition); | |
| }, | |
| _updateLabels: function() | |
| { | |
| var totalSize = this._endPosition - this._startPosition; | |
| if (totalSize > this._chunkSize) { | |
| this.showNext.removeStyleClass("hidden"); | |
| this.showLast.removeStyleClass("hidden"); | |
| } else { | |
| this.showNext.addStyleClass("hidden"); | |
| this.showLast.addStyleClass("hidden"); | |
| } | |
| this.showAll.textContent = WebInspector.UIString("Show all %d", totalSize); | |
| }, | |
| createCells: function() | |
| { | |
| var cell = document.createElement("td"); | |
| if (this.depth) | |
| cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px"); | |
| cell.appendChild(this.showNext); | |
| cell.appendChild(this.showAll); | |
| cell.appendChild(this.showLast); | |
| this._element.appendChild(cell); | |
| var columns = this.dataGrid.columns; | |
| var count = 0; | |
| for (var c in columns) | |
| ++count; | |
| while (--count > 0) { | |
| cell = document.createElement("td"); | |
| this._element.appendChild(cell); | |
| } | |
| }, | |
| setStartPosition: function(from) | |
| { | |
| this._startPosition = from; | |
| this._updateLabels(); | |
| }, | |
| setEndPosition: function(to) | |
| { | |
| this._endPosition = to; | |
| this._updateLabels(); | |
| }, | |
| nodeHeight: function() | |
| { | |
| return 32; | |
| }, | |
| dispose: function() | |
| { | |
| } | |
| }; | |
| WebInspector.ShowMoreDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; | |
| WebInspector.CookiesTable = function(cookieDomain, expandable, deleteCallback, refreshCallback) | |
| { | |
| WebInspector.View.call(this); | |
| this.element.className = "fill"; | |
| this._cookieDomain = cookieDomain; | |
| var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} }; | |
| columns[0].title = WebInspector.UIString("Name"); | |
| columns[0].sortable = true; | |
| columns[0].disclosure = expandable; | |
| columns[0].width = "24%"; | |
| columns[1].title = WebInspector.UIString("Value"); | |
| columns[1].sortable = true; | |
| columns[1].width = "34%"; | |
| columns[2].title = WebInspector.UIString("Domain"); | |
| columns[2].sortable = true; | |
| columns[2].width = "7%"; | |
| columns[3].title = WebInspector.UIString("Path"); | |
| columns[3].sortable = true; | |
| columns[3].width = "7%"; | |
| columns[4].title = WebInspector.UIString("Expires"); | |
| columns[4].sortable = true; | |
| columns[4].width = "7%"; | |
| columns[5].title = WebInspector.UIString("Size"); | |
| columns[5].aligned = "right"; | |
| columns[5].sortable = true; | |
| columns[5].width = "7%"; | |
| columns[6].title = WebInspector.UIString("HTTP"); | |
| columns[6].aligned = "centered"; | |
| columns[6].sortable = true; | |
| columns[6].width = "7%"; | |
| columns[7].title = WebInspector.UIString("Secure"); | |
| columns[7].aligned = "centered"; | |
| columns[7].sortable = true; | |
| columns[7].width = "7%"; | |
| this._dataGrid = new WebInspector.DataGrid(columns, undefined, deleteCallback ? this._onDeleteFromGrid.bind(this, deleteCallback) : undefined); | |
| this._dataGrid.addEventListener("sorting changed", this._rebuildTable, this); | |
| this._dataGrid.refreshCallback = refreshCallback; | |
| this._dataGrid.show(this.element); | |
| this._data = []; | |
| } | |
| WebInspector.CookiesTable.prototype = { | |
| updateWidths: function() | |
| { | |
| if (this._dataGrid) | |
| this._dataGrid.updateWidths(); | |
| }, | |
| setCookies: function(cookies) | |
| { | |
| this._data = [{cookies: cookies}]; | |
| this._rebuildTable(); | |
| }, | |
| addCookiesFolder: function(folderName, cookies) | |
| { | |
| this._data.push({cookies: cookies, folderName: folderName}); | |
| this._rebuildTable(); | |
| }, | |
| get selectedCookie() | |
| { | |
| var node = this._dataGrid.selectedNode; | |
| return node ? node.cookie : null; | |
| }, | |
| _rebuildTable: function() | |
| { | |
| this._dataGrid.rootNode().removeChildren(); | |
| for (var i = 0; i < this._data.length; ++i) { | |
| var item = this._data[i]; | |
| if (item.folderName) { | |
| var groupData = [ item.folderName, "", "", "", "", this._totalSize(item.cookies), "", "" ]; | |
| var groupNode = new WebInspector.DataGridNode(groupData); | |
| groupNode.selectable = true; | |
| this._dataGrid.rootNode().appendChild(groupNode); | |
| groupNode.element.addStyleClass("row-group"); | |
| this._populateNode(groupNode, item.cookies); | |
| groupNode.expand(); | |
| } else | |
| this._populateNode(this._dataGrid.rootNode(), item.cookies); | |
| } | |
| }, | |
| _populateNode: function(parentNode, cookies) | |
| { | |
| var selectedCookie = this.selectedCookie; | |
| parentNode.removeChildren(); | |
| if (!cookies) | |
| return; | |
| this._sortCookies(cookies); | |
| for (var i = 0; i < cookies.length; ++i) { | |
| var cookieNode = this._createGridNode(cookies[i]); | |
| parentNode.appendChild(cookieNode); | |
| if (selectedCookie === cookies[i]) | |
| cookieNode.selected = true; | |
| } | |
| }, | |
| _totalSize: function(cookies) | |
| { | |
| var totalSize = 0; | |
| for (var i = 0; cookies && i < cookies.length; ++i) | |
| totalSize += cookies[i].size; | |
| return totalSize; | |
| }, | |
| _sortCookies: function(cookies) | |
| { | |
| var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1; | |
| function localeCompare(field, cookie1, cookie2) | |
| { | |
| return sortDirection * (cookie1[field] + "").localeCompare(cookie2[field] + "") | |
| } | |
| function numberCompare(field, cookie1, cookie2) | |
| { | |
| return sortDirection * (cookie1[field] - cookie2[field]); | |
| } | |
| function expiresCompare(cookie1, cookie2) | |
| { | |
| if (cookie1.session !== cookie2.session) | |
| return sortDirection * (cookie1.session ? 1 : -1); | |
| if (cookie1.session) | |
| return 0; | |
| return sortDirection * (cookie1.expires - cookie2.expires); | |
| } | |
| var comparator; | |
| switch (parseInt(this._dataGrid.sortColumnIdentifier, 10)) { | |
| case 0: comparator = localeCompare.bind(this, "name"); break; | |
| case 1: comparator = localeCompare.bind(this, "value"); break; | |
| case 2: comparator = localeCompare.bind(this, "domain"); break; | |
| case 3: comparator = localeCompare.bind(this, "path"); break; | |
| case 4: comparator = expiresCompare; break; | |
| case 5: comparator = numberCompare.bind(this, "size"); break; | |
| case 6: comparator = localeCompare.bind(this, "httpOnly"); break; | |
| case 7: comparator = localeCompare.bind(this, "secure"); break; | |
| default: localeCompare.bind(this, "name"); | |
| } | |
| cookies.sort(comparator); | |
| }, | |
| _createGridNode: function(cookie) | |
| { | |
| var data = {}; | |
| data[0] = cookie.name; | |
| data[1] = cookie.value; | |
| data[2] = cookie.domain || ""; | |
| data[3] = cookie.path || ""; | |
| data[4] = cookie.type === WebInspector.Cookie.Type.Request ? "" : | |
| (cookie.session ? WebInspector.UIString("Session") : new Date(cookie.expires).toGMTString()); | |
| data[5] = cookie.size; | |
| const checkmark = "\u2713"; | |
| data[6] = (cookie.httpOnly ? checkmark : ""); | |
| data[7] = (cookie.secure ? checkmark : ""); | |
| var node = new WebInspector.DataGridNode(data); | |
| node.cookie = cookie; | |
| node.selectable = true; | |
| return node; | |
| }, | |
| _onDeleteFromGrid: function(deleteCallback, node) | |
| { | |
| deleteCallback(node.cookie); | |
| } | |
| } | |
| WebInspector.CookiesTable.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.CookieItemsView = function(treeElement, cookieDomain) | |
| { | |
| WebInspector.View.call(this); | |
| this.element.addStyleClass("storage-view"); | |
| this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); | |
| this._deleteButton.visible = false; | |
| this._deleteButton.addEventListener("click", this._deleteButtonClicked, this); | |
| this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); | |
| this._refreshButton.addEventListener("click", this._refreshButtonClicked, this); | |
| this._treeElement = treeElement; | |
| this._cookieDomain = cookieDomain; | |
| this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This site has no cookies.")); | |
| this._emptyView.show(this.element); | |
| this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); | |
| } | |
| WebInspector.CookieItemsView.prototype = { | |
| get statusBarItems() | |
| { | |
| return [this._refreshButton.element, this._deleteButton.element]; | |
| }, | |
| wasShown: function() | |
| { | |
| this._update(); | |
| }, | |
| willHide: function() | |
| { | |
| this._deleteButton.visible = false; | |
| }, | |
| _update: function() | |
| { | |
| WebInspector.Cookies.getCookiesAsync(this._updateWithCookies.bind(this)); | |
| }, | |
| _updateWithCookies: function(allCookies, isAdvanced) | |
| { | |
| this._cookies = isAdvanced ? this._filterCookiesForDomain(allCookies) : allCookies; | |
| if (!this._cookies.length) { | |
| this._emptyView.show(this.element); | |
| this._deleteButton.visible = false; | |
| if (this._cookiesTable) | |
| this._cookiesTable.detach(); | |
| return; | |
| } | |
| if (!this._cookiesTable) | |
| this._cookiesTable = isAdvanced ? new WebInspector.CookiesTable(this._cookieDomain, false, this._deleteCookie.bind(this), this._update.bind(this)) : new WebInspector.SimpleCookiesTable(); | |
| this._cookiesTable.setCookies(this._cookies); | |
| this._emptyView.detach(); | |
| this._cookiesTable.show(this.element); | |
| if (isAdvanced) { | |
| this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length, | |
| Number.bytesToString(this._totalSize)); | |
| this._deleteButton.visible = true; | |
| } | |
| }, | |
| _filterCookiesForDomain: function(allCookies) | |
| { | |
| var cookies = []; | |
| var resourceURLsForDocumentURL = []; | |
| this._totalSize = 0; | |
| function populateResourcesForDocuments(resource) | |
| { | |
| var url = resource.documentURL.asParsedURL(); | |
| if (url && url.host == this._cookieDomain) | |
| resourceURLsForDocumentURL.push(resource.url); | |
| } | |
| WebInspector.forAllResources(populateResourcesForDocuments.bind(this)); | |
| for (var i = 0; i < allCookies.length; ++i) { | |
| var pushed = false; | |
| var size = allCookies[i].size; | |
| for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) { | |
| var resourceURL = resourceURLsForDocumentURL[j]; | |
| if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) { | |
| this._totalSize += size; | |
| if (!pushed) { | |
| pushed = true; | |
| cookies.push(allCookies[i]); | |
| } | |
| } | |
| } | |
| } | |
| return cookies; | |
| }, | |
| _deleteCookie: function(cookie) | |
| { | |
| PageAgent.deleteCookie(cookie.name, this._cookieDomain); | |
| this._update(); | |
| }, | |
| _deleteButtonClicked: function() | |
| { | |
| if (this._cookiesTable.selectedCookie) | |
| this._deleteCookie(this._cookiesTable.selectedCookie); | |
| }, | |
| _refreshButtonClicked: function(event) | |
| { | |
| this._update(); | |
| }, | |
| _contextMenu: function(event) | |
| { | |
| if (!this._cookies.length) { | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| contextMenu.appendItem(WebInspector.UIString("Refresh"), this._update.bind(this)); | |
| contextMenu.show(event); | |
| } | |
| } | |
| } | |
| WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.SimpleCookiesTable = function() | |
| { | |
| WebInspector.View.call(this); | |
| var columns = {}; | |
| columns[0] = {}; | |
| columns[1] = {}; | |
| columns[0].title = WebInspector.UIString("Name"); | |
| columns[1].title = WebInspector.UIString("Value"); | |
| this._dataGrid = new WebInspector.DataGrid(columns); | |
| this._dataGrid.autoSizeColumns(20, 80); | |
| this._dataGrid.show(this.element); | |
| } | |
| WebInspector.SimpleCookiesTable.prototype = { | |
| setCookies: function(cookies) | |
| { | |
| this._dataGrid.rootNode().removeChildren(); | |
| var addedCookies = {}; | |
| for (var i = 0; i < cookies.length; ++i) { | |
| if (addedCookies[cookies[i].name]) | |
| continue; | |
| addedCookies[cookies[i].name] = true; | |
| var data = {}; | |
| data[0] = cookies[i].name; | |
| data[1] = cookies[i].value; | |
| var node = new WebInspector.DataGridNode(data, false); | |
| node.selectable = true; | |
| this._dataGrid.rootNode().appendChild(node); | |
| } | |
| this._dataGrid.rootNode().children[0].selected = true; | |
| } | |
| } | |
| WebInspector.SimpleCookiesTable.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.Cookies = {} | |
| WebInspector.Cookies.getCookiesAsync = function(callback) | |
| { | |
| function mycallback(error, cookies, cookiesString) | |
| { | |
| if (error) | |
| return; | |
| if (cookiesString) | |
| callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false); | |
| else | |
| callback(cookies, true); | |
| } | |
| PageAgent.getCookies(mycallback); | |
| } | |
| WebInspector.Cookies.buildCookiesFromString = function(rawCookieString) | |
| { | |
| var rawCookies = rawCookieString.split(/;\s*/); | |
| var cookies = []; | |
| if (!(/^\s*$/.test(rawCookieString))) { | |
| for (var i = 0; i < rawCookies.length; ++i) { | |
| var cookie = rawCookies[i]; | |
| var delimIndex = cookie.indexOf("="); | |
| var name = cookie.substring(0, delimIndex); | |
| var value = cookie.substring(delimIndex + 1); | |
| var size = name.length + value.length; | |
| cookies.push({ name: name, value: value, size: size }); | |
| } | |
| } | |
| return cookies; | |
| } | |
| WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL) | |
| { | |
| var url = resourceURL.asParsedURL(); | |
| if (!url || !WebInspector.Cookies.cookieDomainMatchesResourceDomain(cookie.domain, url.host)) | |
| return false; | |
| return (url.path.startsWith(cookie.path) | |
| && (!cookie.port || url.port == cookie.port) | |
| && (!cookie.secure || url.scheme === "https")); | |
| } | |
| WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain) | |
| { | |
| if (cookieDomain.charAt(0) !== '.') | |
| return resourceDomain === cookieDomain; | |
| return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i"); | |
| } | |
| WebInspector.ApplicationCacheModel = function() | |
| { | |
| ApplicationCacheAgent.enable(); | |
| InspectorBackend.registerApplicationCacheDispatcher(new WebInspector.ApplicationCacheDispatcher(this)); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); | |
| this._statuses = {}; | |
| this._manifestURLsByFrame = {}; | |
| this._mainFrameNavigated(); | |
| this._onLine = true; | |
| } | |
| WebInspector.ApplicationCacheModel.EventTypes = { | |
| FrameManifestStatusUpdated: "FrameManifestStatusUpdated", | |
| FrameManifestAdded: "FrameManifestAdded", | |
| FrameManifestRemoved: "FrameManifestRemoved", | |
| NetworkStateChanged: "NetworkStateChanged" | |
| } | |
| WebInspector.ApplicationCacheModel.prototype = { | |
| _frameNavigated: function(event) | |
| { | |
| var frame = event.data; | |
| if (frame.isMainFrame()) { | |
| this._mainFrameNavigated(); | |
| return; | |
| } | |
| ApplicationCacheAgent.getManifestForFrame(frame.id, this._manifestForFrameLoaded.bind(this, frame.id)); | |
| }, | |
| _frameDetached: function(event) | |
| { | |
| var frame = event.data; | |
| this._frameManifestRemoved(frame.id); | |
| }, | |
| _mainFrameNavigated: function() | |
| { | |
| ApplicationCacheAgent.getFramesWithManifests(this._framesWithManifestsLoaded.bind(this)); | |
| }, | |
| _manifestForFrameLoaded: function(frameId, error, manifestURL) | |
| { | |
| if (error) { | |
| console.error(error); | |
| return; | |
| } | |
| if (!manifestURL) | |
| this._frameManifestRemoved(frameId); | |
| }, | |
| _framesWithManifestsLoaded: function(error, framesWithManifests) | |
| { | |
| if (error) { | |
| console.error(error); | |
| return; | |
| } | |
| for (var i = 0; i < framesWithManifests.length; ++i) | |
| this._frameManifestUpdated(framesWithManifests[i].frameId, framesWithManifests[i].manifestURL, framesWithManifests[i].status); | |
| }, | |
| _frameManifestUpdated: function(frameId, manifestURL, status) | |
| { | |
| if (status === applicationCache.UNCACHED) { | |
| this._frameManifestRemoved(frameId); | |
| return; | |
| } | |
| if (!manifestURL) | |
| return; | |
| if (this._manifestURLsByFrame[frameId] && manifestURL !== this._manifestURLsByFrame[frameId]) | |
| this._frameManifestRemoved(frameId); | |
| var statusChanged = this._statuses[frameId] !== status; | |
| this._statuses[frameId] = status; | |
| if (!this._manifestURLsByFrame[frameId]) { | |
| this._manifestURLsByFrame[frameId] = manifestURL; | |
| this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestAdded, frameId); | |
| } | |
| if (statusChanged) | |
| this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestStatusUpdated, frameId); | |
| }, | |
| _frameManifestRemoved: function(frameId) | |
| { | |
| if (!this._manifestURLsByFrame[frameId]) | |
| return; | |
| var manifestURL = this._manifestURLsByFrame[frameId]; | |
| delete this._manifestURLsByFrame[frameId]; | |
| delete this._statuses[frameId]; | |
| this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestRemoved, frameId); | |
| }, | |
| frameManifestURL: function(frameId) | |
| { | |
| return this._manifestURLsByFrame[frameId] || ""; | |
| }, | |
| frameManifestStatus: function(frameId) | |
| { | |
| return this._statuses[frameId] || applicationCache.UNCACHED; | |
| }, | |
| get onLine() | |
| { | |
| return this._onLine; | |
| }, | |
| _statusUpdated: function(frameId, manifestURL, status) | |
| { | |
| this._frameManifestUpdated(frameId, manifestURL, status); | |
| }, | |
| requestApplicationCache: function(frameId, callback) | |
| { | |
| function callbackWrapper(error, applicationCache) | |
| { | |
| if (error) { | |
| console.error(error); | |
| callback(null); | |
| return; | |
| } | |
| callback(applicationCache); | |
| } | |
| ApplicationCacheAgent.getApplicationCacheForFrame(frameId, callbackWrapper.bind(this)); | |
| }, | |
| _networkStateUpdated: function(isNowOnline) | |
| { | |
| this._onLine = isNowOnline; | |
| this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.NetworkStateChanged, isNowOnline); | |
| } | |
| } | |
| WebInspector.ApplicationCacheModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.ApplicationCacheDispatcher = function(applicationCacheModel) | |
| { | |
| this._applicationCacheModel = applicationCacheModel; | |
| } | |
| WebInspector.ApplicationCacheDispatcher.prototype = { | |
| applicationCacheStatusUpdated: function(frameId, manifestURL, status) | |
| { | |
| this._applicationCacheModel._statusUpdated(frameId, manifestURL, status); | |
| }, | |
| networkStateUpdated: function(isNowOnline) | |
| { | |
| this._applicationCacheModel._networkStateUpdated(isNowOnline); | |
| } | |
| } | |
| WebInspector.IndexedDBModel = function() | |
| { | |
| IndexedDBAgent.enable(); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameNavigated, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); | |
| this._frames = {}; | |
| this._databases = new Map(); | |
| this._frameIdsBySecurityOrigin = {}; | |
| this._databaseNamesBySecurityOrigin = {}; | |
| this.refreshDatabaseNames(); | |
| } | |
| WebInspector.IndexedDBModel.KeyTypes = { | |
| NumberType: "number", | |
| StringType: "string", | |
| DateType: "date", | |
| ArrayType: "array" | |
| }; | |
| WebInspector.IndexedDBModel.KeyPathTypes = { | |
| NullType: "null", | |
| StringType: "string", | |
| ArrayType: "array" | |
| }; | |
| WebInspector.IndexedDBModel.idbKeyFromKey = function(key) | |
| { | |
| var idbKey; | |
| switch (key.type) { | |
| case WebInspector.IndexedDBModel.KeyTypes.NumberType: | |
| idbKey = key.number; | |
| break; | |
| case WebInspector.IndexedDBModel.KeyTypes.StringType: | |
| idbKey = key.string; | |
| break; | |
| case WebInspector.IndexedDBModel.KeyTypes.DateType: | |
| idbKey = new Date(key.date); | |
| break; | |
| case WebInspector.IndexedDBModel.KeyTypes.ArrayType: | |
| idbKey = []; | |
| for (var i = 0; i < key.array.length; ++i) | |
| idbKey.push(WebInspector.IndexedDBModel.idbKeyFromKey(key.array[i])); | |
| break; | |
| } | |
| return idbKey; | |
| } | |
| WebInspector.IndexedDBModel.keyFromIDBKey = function(idbKey) | |
| { | |
| if (typeof(idbKey) === "undefined" || idbKey === null) | |
| return null; | |
| var key = {}; | |
| switch (typeof(idbKey)) { | |
| case "number": | |
| key.number = idbKey; | |
| key.type = WebInspector.IndexedDBModel.KeyTypes.NumberType; | |
| break; | |
| case "string": | |
| key.string = idbKey; | |
| key.type = WebInspector.IndexedDBModel.KeyTypes.StringType; | |
| break; | |
| case "object": | |
| if (idbKey instanceof Date) { | |
| key.date = idbKey.getTime(); | |
| key.type = WebInspector.IndexedDBModel.KeyTypes.DateType; | |
| } else if (idbKey instanceof Array) { | |
| key.array = []; | |
| for (var i = 0; i < idbKey.length; ++i) | |
| key.array.push(WebInspector.IndexedDBModel.keyFromIDBKey(idbKey[i])); | |
| key.type = WebInspector.IndexedDBModel.KeyTypes.ArrayType; | |
| } | |
| break; | |
| default: | |
| return null; | |
| } | |
| return key; | |
| } | |
| WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange = function(idbKeyRange) | |
| { | |
| var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange; | |
| if (typeof(idbKeyRange) === "undefined" || idbKeyRange === null) | |
| return null; | |
| var keyRange = {}; | |
| keyRange.lower = WebInspector.IndexedDBModel.keyFromIDBKey(idbKeyRange.lower); | |
| keyRange.upper = WebInspector.IndexedDBModel.keyFromIDBKey(idbKeyRange.upper); | |
| keyRange.lowerOpen = idbKeyRange.lowerOpen; | |
| keyRange.upperOpen = idbKeyRange.upperOpen; | |
| return keyRange; | |
| } | |
| WebInspector.IndexedDBModel.idbKeyPathFromKeyPath = function(keyPath) | |
| { | |
| var idbKeyPath; | |
| switch (keyPath.type) { | |
| case WebInspector.IndexedDBModel.KeyPathTypes.NullType: | |
| idbKeyPath = null; | |
| break; | |
| case WebInspector.IndexedDBModel.KeyPathTypes.StringType: | |
| idbKeyPath = keyPath.string; | |
| break; | |
| case WebInspector.IndexedDBModel.KeyPathTypes.ArrayType: | |
| idbKeyPath = keyPath.array; | |
| break; | |
| } | |
| return idbKeyPath; | |
| } | |
| WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath = function(idbKeyPath) | |
| { | |
| if (typeof idbKeyPath === "string") | |
| return "\"" + idbKeyPath + "\""; | |
| if (idbKeyPath instanceof Array) | |
| return "[\"" + idbKeyPath.join("\", \"") + "\"]"; | |
| return null; | |
| } | |
| WebInspector.IndexedDBModel.EventTypes = { | |
| DatabaseAdded: "DatabaseAdded", | |
| DatabaseRemoved: "DatabaseRemoved", | |
| DatabaseLoaded: "DatabaseLoaded" | |
| } | |
| WebInspector.IndexedDBModel.prototype = { | |
| refreshDatabaseNames: function() | |
| { | |
| this._reset(); | |
| if (WebInspector.resourceTreeModel.mainFrame) | |
| this._framesNavigatedRecursively(WebInspector.resourceTreeModel.mainFrame); | |
| }, | |
| refreshDatabase: function(databaseId) | |
| { | |
| this._loadDatabase(databaseId); | |
| }, | |
| _framesNavigatedRecursively: function(resourceTreeFrame) | |
| { | |
| this._processFrameNavigated(resourceTreeFrame); | |
| for (var i = 0; i < resourceTreeFrame.childFrames.length; ++i) | |
| this._framesNavigatedRecursively(resourceTreeFrame.childFrames[i]); | |
| }, | |
| _frameNavigated: function(event) | |
| { | |
| var resourceTreeFrame = event.data; | |
| this._processFrameNavigated(resourceTreeFrame); | |
| }, | |
| _frameDetached: function(event) | |
| { | |
| var resourceTreeFrame = event.data; | |
| this._originRemovedFromFrame(resourceTreeFrame.id); | |
| }, | |
| _reset: function() | |
| { | |
| for (var frameId in this._frames) | |
| this._originRemovedFromFrame(frameId); | |
| }, | |
| _processFrameNavigated: function(resourceTreeFrame) | |
| { | |
| if (resourceTreeFrame.securityOrigin === "null") | |
| return; | |
| if (this._frameIdsBySecurityOrigin[resourceTreeFrame.securityOrigin]) | |
| this._originAddedToFrame(resourceTreeFrame.id, resourceTreeFrame.securityOrigin); | |
| else | |
| this._loadDatabaseNamesForFrame(resourceTreeFrame.id); | |
| }, | |
| _originAddedToFrame: function(frameId, securityOrigin) | |
| { | |
| if (!this._frameIdsBySecurityOrigin[securityOrigin]) { | |
| this._frameIdsBySecurityOrigin[securityOrigin] = []; | |
| this._frameIdsBySecurityOrigin[securityOrigin].push(frameId); | |
| this._databaseNamesBySecurityOrigin[securityOrigin] = []; | |
| } | |
| this._frames[frameId] = new WebInspector.IndexedDBModel.Frame(frameId, securityOrigin); | |
| }, | |
| _originRemovedFromFrame: function(frameId) | |
| { | |
| var currentSecurityOrigin = this._frames[frameId] ? this._frames[frameId].securityOrigin : null; | |
| if (!currentSecurityOrigin) | |
| return; | |
| delete this._frames[frameId]; | |
| var frameIdsForOrigin = this._frameIdsBySecurityOrigin[currentSecurityOrigin]; | |
| for (var i = 0; i < frameIdsForOrigin; ++i) { | |
| if (frameIdsForOrigin[i] === frameId) { | |
| frameIdsForOrigin.splice(i, 1); | |
| break; | |
| } | |
| } | |
| if (!frameIdsForOrigin.length) | |
| this._originRemoved(currentSecurityOrigin); | |
| }, | |
| _originRemoved: function(securityOrigin) | |
| { | |
| var frameIdsForOrigin = this._frameIdsBySecurityOrigin[securityOrigin]; | |
| for (var i = 0; i < frameIdsForOrigin; ++i) | |
| delete this._frames[frameIdsForOrigin[i]]; | |
| delete this._frameIdsBySecurityOrigin[securityOrigin]; | |
| for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i) | |
| this._databaseRemoved(securityOrigin, this._databaseNamesBySecurityOrigin[securityOrigin][i]); | |
| delete this._databaseNamesBySecurityOrigin[securityOrigin]; | |
| }, | |
| _updateOriginDatabaseNames: function(securityOrigin, databaseNames) | |
| { | |
| var newDatabaseNames = {}; | |
| for (var i = 0; i < databaseNames.length; ++i) | |
| newDatabaseNames[databaseNames[i]] = true; | |
| var oldDatabaseNames = {}; | |
| for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i) | |
| oldDatabaseNames[databaseNames[i]] = true; | |
| this._databaseNamesBySecurityOrigin[securityOrigin] = databaseNames; | |
| for (var databaseName in oldDatabaseNames) { | |
| if (!newDatabaseNames[databaseName]) | |
| this._databaseRemoved(securityOrigin, databaseName); | |
| } | |
| for (var databaseName in newDatabaseNames) { | |
| if (!oldDatabaseNames[databaseName]) | |
| this._databaseAdded(securityOrigin, databaseName); | |
| } | |
| if (!this._databaseNamesBySecurityOrigin[securityOrigin].length) | |
| this._originRemoved(securityOrigin); | |
| }, | |
| _databaseAdded: function(securityOrigin, databaseName) | |
| { | |
| var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName); | |
| this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseAdded, databaseId); | |
| }, | |
| _databaseRemoved: function(securityOrigin, databaseName) | |
| { | |
| var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName); | |
| this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseRemoved, databaseId); | |
| }, | |
| _loadDatabaseNamesForFrame: function(frameId) | |
| { | |
| function callback(error, securityOriginWithDatabaseNames) | |
| { | |
| if (error) { | |
| console.error("IndexedDBAgent error: " + error); | |
| return; | |
| } | |
| var databaseNames = securityOriginWithDatabaseNames.databaseNames; | |
| var oldSecurityOrigin = this._frames[frameId] ? this._frames[frameId].securityOrigin : null; | |
| if (!oldSecurityOrigin || oldSecurityOrigin !== securityOriginWithDatabaseNames.securityOrigin) { | |
| this._originRemovedFromFrame(frameId); | |
| this._originAddedToFrame(frameId, securityOriginWithDatabaseNames.securityOrigin); | |
| } | |
| this._updateOriginDatabaseNames(securityOriginWithDatabaseNames.securityOrigin, securityOriginWithDatabaseNames.databaseNames); | |
| } | |
| IndexedDBAgent.requestDatabaseNamesForFrame(frameId, callback.bind(this)); | |
| }, | |
| _assertFrameId: function(databaseId) | |
| { | |
| var frameIds = this._frameIdsBySecurityOrigin[databaseId.securityOrigin]; | |
| if (!frameIds || !frameIds.length) | |
| return null; | |
| return frameIds[0]; | |
| }, | |
| _loadDatabase: function(databaseId) | |
| { | |
| var frameId = this._assertFrameId(databaseId); | |
| if (!frameId) | |
| return; | |
| function callback(error, databaseWithObjectStores) | |
| { | |
| if (error) { | |
| console.error("IndexedDBAgent error: " + error); | |
| return; | |
| } | |
| if (!this._frames[frameId]) | |
| return; | |
| var databaseModel = new WebInspector.IndexedDBModel.Database(databaseId, databaseWithObjectStores.version); | |
| this._databases.put(databaseId, databaseModel); | |
| for (var i = 0; i < databaseWithObjectStores.objectStores.length; ++i) { | |
| var objectStore = databaseWithObjectStores.objectStores[i]; | |
| var objectStoreIDBKeyPath = WebInspector.IndexedDBModel.idbKeyPathFromKeyPath(objectStore.keyPath); | |
| var objectStoreModel = new WebInspector.IndexedDBModel.ObjectStore(objectStore.name, objectStoreIDBKeyPath, objectStore.autoIncrement); | |
| for (var j = 0; j < objectStore.indexes.length; ++j) { | |
| var index = objectStore.indexes[j]; | |
| var indexIDBKeyPath = WebInspector.IndexedDBModel.idbKeyPathFromKeyPath(index.keyPath); | |
| var indexModel = new WebInspector.IndexedDBModel.Index(index.name, indexIDBKeyPath, index.unique, index.multiEntry); | |
| objectStoreModel.indexes[indexModel.name] = indexModel; | |
| } | |
| databaseModel.objectStores[objectStoreModel.name] = objectStoreModel; | |
| } | |
| this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, databaseModel); | |
| } | |
| IndexedDBAgent.requestDatabase(frameId, databaseId.name, callback.bind(this)); | |
| }, | |
| loadObjectStoreData: function(databaseId, objectStoreName, idbKeyRange, skipCount, pageSize, callback) | |
| { | |
| this._requestData(databaseId, databaseId.name, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback); | |
| }, | |
| loadIndexData: function(databaseId, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) | |
| { | |
| this._requestData(databaseId, databaseId.name, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback); | |
| }, | |
| _requestData: function(databaseId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) | |
| { | |
| var frameId = this._assertFrameId(databaseId); | |
| if (!frameId) | |
| return; | |
| function innerCallback(error, dataEntries, hasMore) | |
| { | |
| if (error) { | |
| console.error("IndexedDBAgent error: " + error); | |
| return; | |
| } | |
| if (!this._frames[frameId]) | |
| return; | |
| var entries = []; | |
| for (var i = 0; i < dataEntries.length; ++i) { | |
| var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key); | |
| var primaryKey = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].primaryKey); | |
| var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value); | |
| entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value)); | |
| } | |
| callback(entries, hasMore); | |
| } | |
| var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange); | |
| IndexedDBAgent.requestData(frameId, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback.bind(this)); | |
| } | |
| } | |
| WebInspector.IndexedDBModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.IndexedDBModel.Entry = function(key, primaryKey, value) | |
| { | |
| this.key = key; | |
| this.primaryKey = primaryKey; | |
| this.value = value; | |
| } | |
| WebInspector.IndexedDBModel.Frame = function(frameId, securityOrigin) | |
| { | |
| this.frameId = frameId; | |
| this.securityOrigin = securityOrigin; | |
| this.databaseNames = {}; | |
| } | |
| WebInspector.IndexedDBModel.DatabaseId = function(securityOrigin, name) | |
| { | |
| this.securityOrigin = securityOrigin; | |
| this.name = name; | |
| } | |
| WebInspector.IndexedDBModel.DatabaseId.prototype = { | |
| equals: function(databaseId) | |
| { | |
| return this.name === databaseId.name && this.securityOrigin === databaseId.securityOrigin; | |
| }, | |
| } | |
| WebInspector.IndexedDBModel.Database = function(databaseId, version) | |
| { | |
| this.databaseId = databaseId; | |
| this.version = version; | |
| this.objectStores = {}; | |
| } | |
| WebInspector.IndexedDBModel.ObjectStore = function(name, keyPath, autoIncrement) | |
| { | |
| this.name = name; | |
| this.keyPath = keyPath; | |
| this.autoIncrement = autoIncrement; | |
| this.indexes = {}; | |
| } | |
| WebInspector.IndexedDBModel.ObjectStore.prototype = { | |
| get keyPathString() | |
| { | |
| return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath); | |
| } | |
| } | |
| WebInspector.IndexedDBModel.Index = function(name, keyPath, unique, multiEntry) | |
| { | |
| this.name = name; | |
| this.keyPath = keyPath; | |
| this.unique = unique; | |
| this.multiEntry = multiEntry; | |
| } | |
| WebInspector.IndexedDBModel.Index.prototype = { | |
| get keyPathString() | |
| { | |
| return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath); | |
| } | |
| } | |
| WebInspector.Spectrum = function() | |
| { | |
| this._popover = new WebInspector.Popover(); | |
| this._popover.setCanShrink(false); | |
| this._popover.element.addEventListener("mousedown", consumeEvent, false); | |
| this._containerElement = document.createElement('div'); | |
| this._containerElement.className = "spectrum-container"; | |
| this._containerElement.tabIndex = 0; | |
| this._containerElement.addEventListener("keydown", this._onKeyDown.bind(this), false); | |
| var topElement = this._containerElement.createChild("div", "spectrum-top"); | |
| topElement.createChild("div", "spectrum-fill"); | |
| var topInnerElement = topElement.createChild("div", "spectrum-top-inner fill"); | |
| this._draggerElement = topInnerElement.createChild("div", "spectrum-color"); | |
| this._dragHelperElement = this._draggerElement.createChild("div", "spectrum-sat fill").createChild("div", "spectrum-val fill").createChild("div", "spectrum-dragger"); | |
| this._sliderElement = topInnerElement.createChild("div", "spectrum-hue"); | |
| this.slideHelper = this._sliderElement.createChild("div", "spectrum-slider"); | |
| var rangeContainer = this._containerElement.createChild("div", "spectrum-range-container"); | |
| var alphaLabel = rangeContainer.createChild("label"); | |
| alphaLabel.textContent = WebInspector.UIString("\u03B1:"); | |
| this._alphaElement = rangeContainer.createChild("input", "spectrum-range"); | |
| this._alphaElement.setAttribute("type", "range"); | |
| this._alphaElement.setAttribute("min", "0"); | |
| this._alphaElement.setAttribute("max", "100"); | |
| this._alphaElement.addEventListener("change", alphaDrag.bind(this), false); | |
| var swatchElement = document.createElement("span"); | |
| swatchElement.className = "swatch"; | |
| this._swatchInnerElement = swatchElement.createChild("span", "swatch-inner"); | |
| var displayContainer = this._containerElement.createChild("div"); | |
| displayContainer.appendChild(swatchElement); | |
| this._displayElement = displayContainer.createChild("span", "source-code spectrum-display-value"); | |
| WebInspector.Spectrum.draggable(this._sliderElement, hueDrag.bind(this)); | |
| WebInspector.Spectrum.draggable(this._draggerElement, colorDrag.bind(this), colorDragStart.bind(this)); | |
| function hueDrag(element, dragX, dragY) | |
| { | |
| this.hsv[0] = (dragY / this.slideHeight); | |
| this._onchange(); | |
| } | |
| var initialHelperOffset; | |
| function colorDragStart(element, dragX, dragY) | |
| { | |
| initialHelperOffset = { x: this._dragHelperElement.offsetLeft, y: this._dragHelperElement.offsetTop }; | |
| } | |
| function colorDrag(element, dragX, dragY, event) | |
| { | |
| if (event.shiftKey) { | |
| if (Math.abs(dragX - initialHelperOffset.x) >= Math.abs(dragY - initialHelperOffset.y)) | |
| dragY = initialHelperOffset.y; | |
| else | |
| dragX = initialHelperOffset.x; | |
| } | |
| this.hsv[1] = dragX / this.dragWidth; | |
| this.hsv[2] = (this.dragHeight - dragY) / this.dragHeight; | |
| this._onchange(); | |
| } | |
| function alphaDrag() | |
| { | |
| this.hsv[3] = this._alphaElement.value / 100; | |
| this._onchange(); | |
| } | |
| this._hideProxy = this.hide.bind(this, true); | |
| }; | |
| WebInspector.Spectrum.Events = { | |
| ColorChanged: "ColorChanged", | |
| Hidden: "Hidden" | |
| }; | |
| WebInspector.Spectrum.hsvaToRGBA = function(h, s, v, a) | |
| { | |
| var r, g, b; | |
| var i = Math.floor(h * 6); | |
| var f = h * 6 - i; | |
| var p = v * (1 - s); | |
| var q = v * (1 - f * s); | |
| var t = v * (1 - (1 - f) * s); | |
| switch(i % 6) { | |
| case 0: | |
| r = v, g = t, b = p; | |
| break; | |
| case 1: | |
| r = q, g = v, b = p; | |
| break; | |
| case 2: | |
| r = p, g = v, b = t; | |
| break; | |
| case 3: | |
| r = p, g = q, b = v; | |
| break; | |
| case 4: | |
| r = t, g = p, b = v; | |
| break; | |
| case 5: | |
| r = v, g = p, b = q; | |
| break; | |
| } | |
| return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a]; | |
| }; | |
| WebInspector.Spectrum.rgbaToHSVA = function(r, g, b, a) | |
| { | |
| r = r / 255; | |
| g = g / 255; | |
| b = b / 255; | |
| var max = Math.max(r, g, b); | |
| var min = Math.min(r, g, b); | |
| var h; | |
| var s; | |
| var v = max; | |
| var d = max - min; | |
| s = max ? d / max : 0; | |
| if(max === min) { | |
| h = 0; | |
| } else { | |
| switch(max) { | |
| case r: | |
| h = (g - b) / d + (g < b ? 6 : 0); | |
| break; | |
| case g: | |
| h = (b - r) / d + 2; | |
| break; | |
| case b: | |
| h = (r - g) / d + 4; | |
| break; | |
| } | |
| h /= 6; | |
| } | |
| return [h, s, v, a]; | |
| }; | |
| WebInspector.Spectrum.draggable = function(element, onmove, onstart, onstop) { | |
| var doc = document; | |
| var dragging; | |
| var offset; | |
| var scrollOffset; | |
| var maxHeight; | |
| var maxWidth; | |
| function consume(e) | |
| { | |
| e.consume(true); | |
| } | |
| function move(e) | |
| { | |
| if (dragging) { | |
| var dragX = Math.max(0, Math.min(e.pageX - offset.left + scrollOffset.left, maxWidth)); | |
| var dragY = Math.max(0, Math.min(e.pageY - offset.top + scrollOffset.top, maxHeight)); | |
| if (onmove) | |
| onmove(element, dragX, dragY, e); | |
| } | |
| } | |
| function start(e) | |
| { | |
| var rightClick = e.which ? (e.which === 3) : (e.button === 2); | |
| if (!rightClick && !dragging) { | |
| if (onstart) | |
| onstart(element, e) | |
| dragging = true; | |
| maxHeight = element.clientHeight; | |
| maxWidth = element.clientWidth; | |
| scrollOffset = element.scrollOffset(); | |
| offset = element.totalOffset(); | |
| doc.addEventListener("selectstart", consume, false); | |
| doc.addEventListener("dragstart", consume, false); | |
| doc.addEventListener("mousemove", move, false); | |
| doc.addEventListener("mouseup", stop, false); | |
| move(e); | |
| consume(e); | |
| } | |
| } | |
| function stop(e) | |
| { | |
| if (dragging) { | |
| doc.removeEventListener("selectstart", consume, false); | |
| doc.removeEventListener("dragstart", consume, false); | |
| doc.removeEventListener("mousemove", move, false); | |
| doc.removeEventListener("mouseup", stop, false); | |
| if (onstop) | |
| onstop(element, e); | |
| } | |
| dragging = false; | |
| } | |
| element.addEventListener("mousedown", start, false); | |
| }; | |
| WebInspector.Spectrum.prototype = { | |
| set color(color) | |
| { | |
| var rgba = (color.rgba || color.rgb).slice(0); | |
| if (rgba.length === 3) | |
| rgba[3] = 1; | |
| this.hsv = WebInspector.Spectrum.rgbaToHSVA(rgba[0], rgba[1], rgba[2], rgba[3]); | |
| }, | |
| get color() | |
| { | |
| var rgba = WebInspector.Spectrum.hsvaToRGBA(this.hsv[0], this.hsv[1], this.hsv[2], this.hsv[3]); | |
| var color; | |
| if (rgba[3] === 1) | |
| color = WebInspector.Color.fromRGB(rgba[0], rgba[1], rgba[2]); | |
| else | |
| color = WebInspector.Color.fromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); | |
| var colorValue = color.toString(this.outputColorFormat); | |
| if (!colorValue) | |
| colorValue = color.toString(); | |
| return new WebInspector.Color(colorValue); | |
| }, | |
| get outputColorFormat() | |
| { | |
| var cf = WebInspector.Color.Format; | |
| var format = this._originalFormat; | |
| if (this.hsv[3] === 1) { | |
| if (format === cf.RGBA) | |
| format = cf.RGB; | |
| else if (format === cf.HSLA) | |
| format = cf.HSL; | |
| } else { | |
| if (format === cf.HSL || format === cf.HSLA) | |
| format = cf.HSLA; | |
| else | |
| format = cf.RGBA; | |
| } | |
| return format; | |
| }, | |
| get colorHueOnly() | |
| { | |
| var rgba = WebInspector.Spectrum.hsvaToRGBA(this.hsv[0], 1, 1, 1); | |
| return WebInspector.Color.fromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); | |
| }, | |
| set displayText(text) | |
| { | |
| this._displayElement.textContent = text; | |
| }, | |
| get visible() | |
| { | |
| return this._popover.visible; | |
| }, | |
| _onchange: function() | |
| { | |
| this._updateUI(); | |
| this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChanged, this.color); | |
| }, | |
| _updateHelperLocations: function() | |
| { | |
| var h = this.hsv[0]; | |
| var s = this.hsv[1]; | |
| var v = this.hsv[2]; | |
| var dragX = s * this.dragWidth; | |
| var dragY = this.dragHeight - (v * this.dragHeight); | |
| dragX = Math.max(-this._dragHelperElementHeight, | |
| Math.min(this.dragWidth - this._dragHelperElementHeight, dragX - this._dragHelperElementHeight)); | |
| dragY = Math.max(-this._dragHelperElementHeight, | |
| Math.min(this.dragHeight - this._dragHelperElementHeight, dragY - this._dragHelperElementHeight)); | |
| this._dragHelperElement.positionAt(dragX, dragY); | |
| var slideY = (h * this.slideHeight) - this.slideHelperHeight; | |
| this.slideHelper.style.top = slideY + "px"; | |
| this._alphaElement.value = this.hsv[3] * 100; | |
| }, | |
| _updateUI: function() | |
| { | |
| this._updateHelperLocations(); | |
| var rgb = (this.color.rgba || this.color.rgb).slice(0); | |
| if (rgb.length === 3) | |
| rgb[3] = 1; | |
| var rgbHueOnly = this.colorHueOnly.rgb; | |
| var flatColor = "rgb(" + rgbHueOnly[0] + ", " + rgbHueOnly[1] + ", " + rgbHueOnly[2] + ")"; | |
| var fullColor = "rgba(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ", " + rgb[3] + ")"; | |
| this._draggerElement.style.backgroundColor = flatColor; | |
| this._swatchInnerElement.style.backgroundColor = fullColor; | |
| this._alphaElement.value = this.hsv[3] * 100; | |
| }, | |
| toggle: function(element, color, format) | |
| { | |
| if (this.visible) | |
| this.hide(true); | |
| else | |
| this.show(element, color, format); | |
| return this.visible; | |
| }, | |
| show: function(element, color, format) | |
| { | |
| if (this.visible) { | |
| if (this.anchorElement === element) | |
| return false; | |
| this.hide(true); | |
| } | |
| this.reposition(element); | |
| this.anchorElement = element; | |
| document.addEventListener("mousedown", this._hideProxy, false); | |
| window.addEventListener("blur", this._hideProxy, false); | |
| this.slideHeight = this._sliderElement.offsetHeight; | |
| this.dragWidth = this._draggerElement.offsetWidth; | |
| this.dragHeight = this._draggerElement.offsetHeight; | |
| this._dragHelperElementHeight = this._dragHelperElement.offsetHeight / 2; | |
| this.slideHelperHeight = this.slideHelper.offsetHeight / 2; | |
| this.color = color; | |
| this._originalFormat = format || color.format; | |
| this._updateUI(); | |
| return true; | |
| }, | |
| reposition: function(element) | |
| { | |
| if (!this._previousFocusElement) | |
| this._previousFocusElement = WebInspector.currentFocusElement(); | |
| this._popover.show(this._containerElement, element); | |
| WebInspector.setCurrentFocusElement(this._containerElement); | |
| }, | |
| hide: function(commitEdit) | |
| { | |
| this._popover.hide(); | |
| document.removeEventListener("mousedown", this._hideProxy, false); | |
| window.removeEventListener("blur", this._hideProxy, false); | |
| this.dispatchEventToListeners(WebInspector.Spectrum.Events.Hidden, !!commitEdit); | |
| WebInspector.setCurrentFocusElement(this._previousFocusElement); | |
| delete this._previousFocusElement; | |
| delete this.anchorElement; | |
| }, | |
| _onKeyDown: function(event) | |
| { | |
| if (event.keyIdentifier === "Enter") { | |
| this.hide(true); | |
| event.consume(true); | |
| return; | |
| } | |
| if (event.keyIdentifier === "U+001B") { | |
| this.hide(false); | |
| event.consume(true); | |
| } | |
| } | |
| } | |
| WebInspector.Spectrum.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.SidebarPane = function(title) | |
| { | |
| this.element = document.createElement("div"); | |
| this.element.className = "pane"; | |
| this.titleElement = document.createElement("div"); | |
| this.titleElement.className = "title"; | |
| this.titleElement.tabIndex = 0; | |
| this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false); | |
| this.titleElement.addEventListener("keydown", this._onTitleKeyDown.bind(this), false); | |
| this.bodyElement = document.createElement("div"); | |
| this.bodyElement.className = "body"; | |
| this.element.appendChild(this.titleElement); | |
| this.element.appendChild(this.bodyElement); | |
| this.title = title; | |
| this.growbarVisible = false; | |
| this.expanded = false; | |
| } | |
| WebInspector.SidebarPane.prototype = { | |
| get title() | |
| { | |
| return this._title; | |
| }, | |
| set title(x) | |
| { | |
| if (this._title === x) | |
| return; | |
| this._title = x; | |
| this.titleElement.textContent = x; | |
| }, | |
| get growbarVisible() | |
| { | |
| return this._growbarVisible; | |
| }, | |
| set growbarVisible(x) | |
| { | |
| if (this._growbarVisible === x) | |
| return; | |
| this._growbarVisible = x; | |
| if (x && !this._growbarElement) { | |
| this._growbarElement = document.createElement("div"); | |
| this._growbarElement.className = "growbar"; | |
| this.element.appendChild(this._growbarElement); | |
| } else if (!x && this._growbarElement) { | |
| if (this._growbarElement.parentNode) | |
| this._growbarElement.parentNode(this._growbarElement); | |
| delete this._growbarElement; | |
| } | |
| }, | |
| get expanded() | |
| { | |
| return this._expanded; | |
| }, | |
| set expanded(x) | |
| { | |
| if (x) | |
| this.expand(); | |
| else | |
| this.collapse(); | |
| }, | |
| expand: function() | |
| { | |
| if (this._expanded) | |
| return; | |
| this._expanded = true; | |
| this.element.addStyleClass("expanded"); | |
| this.onexpand(); | |
| }, | |
| onexpand: function() | |
| { | |
| }, | |
| collapse: function() | |
| { | |
| if (!this._expanded) | |
| return; | |
| this._expanded = false; | |
| this.element.removeStyleClass("expanded"); | |
| }, | |
| toggleExpanded: function() | |
| { | |
| this.expanded = !this.expanded; | |
| }, | |
| _onTitleKeyDown: function(event) | |
| { | |
| if (isEnterKey(event) || event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code) | |
| this.toggleExpanded(); | |
| } | |
| } | |
| WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.ElementsTreeOutline = function(omitRootDOMNode, selectEnabled, showInElementsPanelEnabled, contextMenuCallback, setPseudoClassCallback) | |
| { | |
| this.element = document.createElement("ol"); | |
| this.element.addEventListener("mousedown", this._onmousedown.bind(this), false); | |
| this.element.addEventListener("mousemove", this._onmousemove.bind(this), false); | |
| this.element.addEventListener("mouseout", this._onmouseout.bind(this), false); | |
| this.element.addEventListener("dragstart", this._ondragstart.bind(this), false); | |
| this.element.addEventListener("dragover", this._ondragover.bind(this), false); | |
| this.element.addEventListener("dragleave", this._ondragleave.bind(this), false); | |
| this.element.addEventListener("drop", this._ondrop.bind(this), false); | |
| this.element.addEventListener("dragend", this._ondragend.bind(this), false); | |
| TreeOutline.call(this, this.element); | |
| this._includeRootDOMNode = !omitRootDOMNode; | |
| this._selectEnabled = selectEnabled; | |
| this._showInElementsPanelEnabled = showInElementsPanelEnabled; | |
| this._rootDOMNode = null; | |
| this._selectDOMNode = null; | |
| this._eventSupport = new WebInspector.Object(); | |
| this._editing = false; | |
| this._visible = false; | |
| this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); | |
| this._contextMenuCallback = contextMenuCallback; | |
| this._setPseudoClassCallback = setPseudoClassCallback; | |
| this._createNodeDecorators(); | |
| } | |
| WebInspector.ElementsTreeOutline.Events = { | |
| SelectedNodeChanged: "SelectedNodeChanged" | |
| } | |
| WebInspector.ElementsTreeOutline.MappedCharToEntity = { | |
| "\u00a0": "nbsp", | |
| "\u2002": "ensp", | |
| "\u2003": "emsp", | |
| "\u2009": "thinsp", | |
| "\u200b": "#8203", | |
| "\u200c": "zwnj", | |
| "\u200d": "zwj", | |
| "\u200e": "lrm", | |
| "\u200f": "rlm", | |
| "\u202a": "#8234", | |
| "\u202b": "#8235", | |
| "\u202c": "#8236", | |
| "\u202d": "#8237", | |
| "\u202e": "#8238" | |
| } | |
| WebInspector.ElementsTreeOutline.prototype = { | |
| _createNodeDecorators: function() | |
| { | |
| this._nodeDecorators = []; | |
| this._nodeDecorators.push(new WebInspector.ElementsTreeOutline.PseudoStateDecorator()); | |
| }, | |
| wireToDomAgent: function() | |
| { | |
| this._elementsTreeUpdater = new WebInspector.ElementsTreeUpdater(this); | |
| }, | |
| setVisible: function(visible) | |
| { | |
| this._visible = visible; | |
| if (!this._visible) | |
| return; | |
| this._updateModifiedNodes(); | |
| if (this._selectedDOMNode) | |
| this._revealAndSelectNode(this._selectedDOMNode, false); | |
| }, | |
| addEventListener: function(eventType, listener, thisObject) | |
| { | |
| this._eventSupport.addEventListener(eventType, listener, thisObject); | |
| }, | |
| removeEventListener: function(eventType, listener, thisObject) | |
| { | |
| this._eventSupport.removeEventListener(eventType, listener, thisObject); | |
| }, | |
| get rootDOMNode() | |
| { | |
| return this._rootDOMNode; | |
| }, | |
| set rootDOMNode(x) | |
| { | |
| if (this._rootDOMNode === x) | |
| return; | |
| this._rootDOMNode = x; | |
| this._isXMLMimeType = x && x.isXMLNode(); | |
| this.update(); | |
| }, | |
| get isXMLMimeType() | |
| { | |
| return this._isXMLMimeType; | |
| }, | |
| selectedDOMNode: function() | |
| { | |
| return this._selectedDOMNode; | |
| }, | |
| selectDOMNode: function(node, focus) | |
| { | |
| if (this._selectedDOMNode === node) { | |
| this._revealAndSelectNode(node, !focus); | |
| return; | |
| } | |
| this._selectedDOMNode = node; | |
| this._revealAndSelectNode(node, !focus); | |
| if (this._selectedDOMNode === node) | |
| this._selectedNodeChanged(); | |
| }, | |
| get editing() | |
| { | |
| return this._editing; | |
| }, | |
| update: function() | |
| { | |
| var selectedNode = this.selectedTreeElement ? this.selectedTreeElement.representedObject : null; | |
| this.removeChildren(); | |
| if (!this.rootDOMNode) | |
| return; | |
| var treeElement; | |
| if (this._includeRootDOMNode) { | |
| treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode); | |
| treeElement.selectable = this._selectEnabled; | |
| this.appendChild(treeElement); | |
| } else { | |
| var node = this.rootDOMNode.firstChild; | |
| while (node) { | |
| treeElement = new WebInspector.ElementsTreeElement(node); | |
| treeElement.selectable = this._selectEnabled; | |
| this.appendChild(treeElement); | |
| node = node.nextSibling; | |
| } | |
| } | |
| if (selectedNode) | |
| this._revealAndSelectNode(selectedNode, true); | |
| }, | |
| updateSelection: function() | |
| { | |
| if (!this.selectedTreeElement) | |
| return; | |
| var element = this.treeOutline.selectedTreeElement; | |
| element.updateSelection(); | |
| }, | |
| updateOpenCloseTags: function(node) | |
| { | |
| var treeElement = this.findTreeElement(node); | |
| if (treeElement) | |
| treeElement.updateTitle(); | |
| var children = treeElement.children; | |
| var closingTagElement = children[children.length - 1]; | |
| if (closingTagElement && closingTagElement._elementCloseTag) | |
| closingTagElement.updateTitle(); | |
| }, | |
| _selectedNodeChanged: function() | |
| { | |
| this._eventSupport.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedDOMNode); | |
| }, | |
| findTreeElement: function(node) | |
| { | |
| function isAncestorNode(ancestor, node) | |
| { | |
| return ancestor.isAncestor(node); | |
| } | |
| function parentNode(node) | |
| { | |
| return node.parentNode; | |
| } | |
| var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode); | |
| if (!treeElement && node.nodeType() === Node.TEXT_NODE) { | |
| treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode); | |
| } | |
| return treeElement; | |
| }, | |
| createTreeElementFor: function(node) | |
| { | |
| var treeElement = this.findTreeElement(node); | |
| if (treeElement) | |
| return treeElement; | |
| if (!node.parentNode) | |
| return null; | |
| treeElement = this.createTreeElementFor(node.parentNode); | |
| if (treeElement && treeElement.showChild(node.index)) | |
| return treeElement.children[node.index]; | |
| return null; | |
| }, | |
| set suppressRevealAndSelect(x) | |
| { | |
| if (this._suppressRevealAndSelect === x) | |
| return; | |
| this._suppressRevealAndSelect = x; | |
| }, | |
| _revealAndSelectNode: function(node, omitFocus) | |
| { | |
| if (!node || this._suppressRevealAndSelect) | |
| return; | |
| var treeElement = this.createTreeElementFor(node); | |
| if (!treeElement) | |
| return; | |
| treeElement.revealAndSelect(omitFocus); | |
| }, | |
| _treeElementFromEvent: function(event) | |
| { | |
| var scrollContainer = this.element.parentElement; | |
| var x = scrollContainer.totalOffsetLeft() + scrollContainer.offsetWidth - 36; | |
| var y = event.pageY; | |
| var elementUnderMouse = this.treeElementFromPoint(x, y); | |
| var elementAboveMouse = this.treeElementFromPoint(x, y - 2); | |
| var element; | |
| if (elementUnderMouse === elementAboveMouse) | |
| element = elementUnderMouse; | |
| else | |
| element = this.treeElementFromPoint(x, y + 2); | |
| return element; | |
| }, | |
| _onmousedown: function(event) | |
| { | |
| var element = this._treeElementFromEvent(event); | |
| if (!element || element.isEventWithinDisclosureTriangle(event)) | |
| return; | |
| element.select(); | |
| }, | |
| _onmousemove: function(event) | |
| { | |
| var element = this._treeElementFromEvent(event); | |
| if (element && this._previousHoveredElement === element) | |
| return; | |
| if (this._previousHoveredElement) { | |
| this._previousHoveredElement.hovered = false; | |
| delete this._previousHoveredElement; | |
| } | |
| if (element) { | |
| element.hovered = true; | |
| this._previousHoveredElement = element; | |
| } | |
| WebInspector.domAgent.highlightDOMNode(element ? element.representedObject.id : 0); | |
| }, | |
| _onmouseout: function(event) | |
| { | |
| var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); | |
| if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element)) | |
| return; | |
| if (this._previousHoveredElement) { | |
| this._previousHoveredElement.hovered = false; | |
| delete this._previousHoveredElement; | |
| } | |
| WebInspector.domAgent.hideDOMNodeHighlight(); | |
| }, | |
| _ondragstart: function(event) | |
| { | |
| var treeElement = this._treeElementFromEvent(event); | |
| if (!treeElement) | |
| return false; | |
| if (!this._isValidDragSourceOrTarget(treeElement)) | |
| return false; | |
| if (treeElement.representedObject.nodeName() === "BODY" || treeElement.representedObject.nodeName() === "HEAD") | |
| return false; | |
| event.dataTransfer.setData("text/plain", treeElement.listItemElement.textContent); | |
| event.dataTransfer.effectAllowed = "copyMove"; | |
| this._treeElementBeingDragged = treeElement; | |
| WebInspector.domAgent.hideDOMNodeHighlight(); | |
| return true; | |
| }, | |
| _ondragover: function(event) | |
| { | |
| if (!this._treeElementBeingDragged) | |
| return false; | |
| var treeElement = this._treeElementFromEvent(event); | |
| if (!this._isValidDragSourceOrTarget(treeElement)) | |
| return false; | |
| var node = treeElement.representedObject; | |
| while (node) { | |
| if (node === this._treeElementBeingDragged.representedObject) | |
| return false; | |
| node = node.parentNode; | |
| } | |
| treeElement.updateSelection(); | |
| treeElement.listItemElement.addStyleClass("elements-drag-over"); | |
| this._dragOverTreeElement = treeElement; | |
| event.preventDefault(); | |
| event.dataTransfer.dropEffect = 'move'; | |
| return false; | |
| }, | |
| _ondragleave: function(event) | |
| { | |
| this._clearDragOverTreeElementMarker(); | |
| event.preventDefault(); | |
| return false; | |
| }, | |
| _isValidDragSourceOrTarget: function(treeElement) | |
| { | |
| if (!treeElement) | |
| return false; | |
| var node = treeElement.representedObject; | |
| if (!(node instanceof WebInspector.DOMNode)) | |
| return false; | |
| if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE) | |
| return false; | |
| return true; | |
| }, | |
| _ondrop: function(event) | |
| { | |
| event.preventDefault(); | |
| var treeElement = this._treeElementFromEvent(event); | |
| if (treeElement) | |
| this._doMove(treeElement); | |
| }, | |
| _doMove: function(treeElement) | |
| { | |
| if (!this._treeElementBeingDragged) | |
| return; | |
| var parentNode; | |
| var anchorNode; | |
| if (treeElement._elementCloseTag) { | |
| parentNode = treeElement.representedObject; | |
| } else { | |
| var dragTargetNode = treeElement.representedObject; | |
| parentNode = dragTargetNode.parentNode; | |
| anchorNode = dragTargetNode; | |
| } | |
| var wasExpanded = this._treeElementBeingDragged.expanded; | |
| this._treeElementBeingDragged.representedObject.moveTo(parentNode, anchorNode, this._selectNodeAfterEdit.bind(this, null, wasExpanded)); | |
| delete this._treeElementBeingDragged; | |
| }, | |
| _ondragend: function(event) | |
| { | |
| event.preventDefault(); | |
| this._clearDragOverTreeElementMarker(); | |
| delete this._treeElementBeingDragged; | |
| }, | |
| _clearDragOverTreeElementMarker: function() | |
| { | |
| if (this._dragOverTreeElement) { | |
| this._dragOverTreeElement.updateSelection(); | |
| this._dragOverTreeElement.listItemElement.removeStyleClass("elements-drag-over"); | |
| delete this._dragOverTreeElement; | |
| } | |
| }, | |
| _contextMenuEventFired: function(event) | |
| { | |
| if (!this._showInElementsPanelEnabled) | |
| return; | |
| var treeElement = this._treeElementFromEvent(event); | |
| if (!treeElement) | |
| return; | |
| function focusElement() | |
| { | |
| WebInspector.domAgent.inspectElement(treeElement.representedObject.id); | |
| } | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this)); | |
| contextMenu.show(event); | |
| }, | |
| populateContextMenu: function(contextMenu, event) | |
| { | |
| var treeElement = this._treeElementFromEvent(event); | |
| if (!treeElement) | |
| return false; | |
| var isTag = treeElement.representedObject.nodeType() === Node.ELEMENT_NODE; | |
| var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node"); | |
| if (textNode && textNode.hasStyleClass("bogus")) | |
| textNode = null; | |
| var commentNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-comment"); | |
| contextMenu.appendApplicableItems(event.target); | |
| if (textNode) { | |
| contextMenu.appendSeparator(); | |
| treeElement._populateTextContextMenu(contextMenu, textNode); | |
| } else if (isTag) { | |
| contextMenu.appendSeparator(); | |
| treeElement._populateTagContextMenu(contextMenu, event); | |
| } else if (commentNode) { | |
| contextMenu.appendSeparator(); | |
| treeElement._populateNodeContextMenu(contextMenu, textNode); | |
| } | |
| }, | |
| adjustCollapsedRange: function() | |
| { | |
| }, | |
| _updateModifiedNodes: function() | |
| { | |
| if (this._elementsTreeUpdater) | |
| this._elementsTreeUpdater._updateModifiedNodes(); | |
| }, | |
| _populateContextMenu: function(contextMenu, node) | |
| { | |
| if (this._contextMenuCallback) | |
| this._contextMenuCallback(contextMenu, node); | |
| }, | |
| handleShortcut: function(event) | |
| { | |
| var node = this.selectedDOMNode(); | |
| var treeElement = this.getCachedTreeElement(node); | |
| if (!node || !treeElement) | |
| return; | |
| if (event.keyIdentifier === "F2") { | |
| this._toggleEditAsHTML(node); | |
| return; | |
| } | |
| if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && node.parentNode) { | |
| if (event.keyIdentifier === "Up" && node.previousSibling) { | |
| node.moveTo(node.parentNode, node.previousSibling, this._selectNodeAfterEdit.bind(this, null, treeElement.expanded)); | |
| return; | |
| } | |
| if (event.keyIdentifier === "Down" && node.nextSibling) { | |
| node.moveTo(node.parentNode, node.nextSibling.nextSibling, this._selectNodeAfterEdit.bind(this, null, treeElement.expanded)); | |
| return; | |
| } | |
| } | |
| }, | |
| _toggleEditAsHTML: function(node) | |
| { | |
| var treeElement = this.getCachedTreeElement(node); | |
| if (!treeElement) | |
| return; | |
| if (treeElement._editing && treeElement._htmlEditElement && WebInspector.isBeingEdited(treeElement._htmlEditElement)) | |
| treeElement._editing.commit(); | |
| else | |
| treeElement._editAsHTML(); | |
| }, | |
| _selectNodeAfterEdit: function(fallbackNode, wasExpanded, error, nodeId) | |
| { | |
| if (error) | |
| return; | |
| this._updateModifiedNodes(); | |
| var newNode = WebInspector.domAgent.nodeForId(nodeId) || fallbackNode; | |
| if (!newNode) | |
| return; | |
| this.selectDOMNode(newNode, true); | |
| var newTreeItem = this.findTreeElement(newNode); | |
| if (wasExpanded) { | |
| if (newTreeItem) | |
| newTreeItem.expand(); | |
| } | |
| return newTreeItem; | |
| } | |
| } | |
| WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype; | |
| WebInspector.ElementsTreeOutline.ElementDecorator = function() | |
| { | |
| } | |
| WebInspector.ElementsTreeOutline.ElementDecorator.prototype = { | |
| decorate: function(node) | |
| { | |
| }, | |
| decorateAncestor: function(node) | |
| { | |
| } | |
| } | |
| WebInspector.ElementsTreeOutline.PseudoStateDecorator = function() | |
| { | |
| WebInspector.ElementsTreeOutline.ElementDecorator.call(this); | |
| } | |
| WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName = "pseudoState"; | |
| WebInspector.ElementsTreeOutline.PseudoStateDecorator.prototype = { | |
| decorate: function(node) | |
| { | |
| if (node.nodeType() !== Node.ELEMENT_NODE) | |
| return null; | |
| var propertyValue = node.getUserProperty(WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName); | |
| if (!propertyValue) | |
| return null; | |
| return WebInspector.UIString("Element state: %s", ":" + propertyValue.join(", :")); | |
| }, | |
| decorateAncestor: function(node) | |
| { | |
| if (node.nodeType() !== Node.ELEMENT_NODE) | |
| return null; | |
| var descendantCount = node.descendantUserPropertyCount(WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName); | |
| if (!descendantCount) | |
| return null; | |
| if (descendantCount === 1) | |
| return WebInspector.UIString("%d descendant with forced state", descendantCount); | |
| return WebInspector.UIString("%d descendants with forced state", descendantCount); | |
| } | |
| } | |
| WebInspector.ElementsTreeOutline.PseudoStateDecorator.prototype.__proto__ = WebInspector.ElementsTreeOutline.ElementDecorator.prototype; | |
| WebInspector.ElementsTreeElement = function(node, elementCloseTag) | |
| { | |
| this._elementCloseTag = elementCloseTag; | |
| var hasChildrenOverride = !elementCloseTag && node.hasChildNodes() && !this._showInlineText(node); | |
| TreeElement.call(this, "", node, hasChildrenOverride); | |
| if (this.representedObject.nodeType() == Node.ELEMENT_NODE && !elementCloseTag) | |
| this._canAddAttributes = true; | |
| this._searchQuery = null; | |
| this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit; | |
| } | |
| WebInspector.ElementsTreeElement.InitialChildrenLimit = 500; | |
| WebInspector.ElementsTreeElement.ForbiddenClosingTagElements = [ | |
| "area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame", | |
| "hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source" | |
| ].keySet(); | |
| WebInspector.ElementsTreeElement.EditTagBlacklist = [ | |
| "html", "head", "body" | |
| ].keySet(); | |
| WebInspector.ElementsTreeElement.prototype = { | |
| highlightSearchResults: function(searchQuery) | |
| { | |
| if (this._searchQuery !== searchQuery) { | |
| this._updateSearchHighlight(false); | |
| delete this._highlightResult; | |
| } | |
| this._searchQuery = searchQuery; | |
| this._searchHighlightsVisible = true; | |
| this.updateTitle(true); | |
| }, | |
| hideSearchHighlights: function() | |
| { | |
| delete this._searchHighlightsVisible; | |
| this._updateSearchHighlight(false); | |
| }, | |
| _updateSearchHighlight: function(show) | |
| { | |
| if (!this._highlightResult) | |
| return; | |
| function updateEntryShow(entry) | |
| { | |
| switch (entry.type) { | |
| case "added": | |
| entry.parent.insertBefore(entry.node, entry.nextSibling); | |
| break; | |
| case "changed": | |
| entry.node.textContent = entry.newText; | |
| break; | |
| } | |
| } | |
| function updateEntryHide(entry) | |
| { | |
| switch (entry.type) { | |
| case "added": | |
| if (entry.node.parentElement) | |
| entry.node.parentElement.removeChild(entry.node); | |
| break; | |
| case "changed": | |
| entry.node.textContent = entry.oldText; | |
| break; | |
| } | |
| } | |
| if (show) { | |
| for (var i = 0, size = this._highlightResult.length; i < size; ++i) | |
| updateEntryShow(this._highlightResult[i]); | |
| } else { | |
| for (var i = (this._highlightResult.length - 1); i >= 0; --i) | |
| updateEntryHide(this._highlightResult[i]); | |
| } | |
| }, | |
| get hovered() | |
| { | |
| return this._hovered; | |
| }, | |
| set hovered(x) | |
| { | |
| if (this._hovered === x) | |
| return; | |
| this._hovered = x; | |
| if (this.listItemElement) { | |
| if (x) { | |
| this.updateSelection(); | |
| this.listItemElement.addStyleClass("hovered"); | |
| } else { | |
| this.listItemElement.removeStyleClass("hovered"); | |
| } | |
| } | |
| }, | |
| get expandedChildrenLimit() | |
| { | |
| return this._expandedChildrenLimit; | |
| }, | |
| set expandedChildrenLimit(x) | |
| { | |
| if (this._expandedChildrenLimit === x) | |
| return; | |
| this._expandedChildrenLimit = x; | |
| if (this.treeOutline && !this._updateChildrenInProgress) | |
| this._updateChildren(true); | |
| }, | |
| get expandedChildCount() | |
| { | |
| var count = this.children.length; | |
| if (count && this.children[count - 1]._elementCloseTag) | |
| count--; | |
| if (count && this.children[count - 1].expandAllButton) | |
| count--; | |
| return count; | |
| }, | |
| showChild: function(index) | |
| { | |
| if (this._elementCloseTag) | |
| return; | |
| if (index >= this.expandedChildrenLimit) { | |
| this._expandedChildrenLimit = index + 1; | |
| this._updateChildren(true); | |
| } | |
| return this.expandedChildCount > index; | |
| }, | |
| updateSelection: function() | |
| { | |
| var listItemElement = this.listItemElement; | |
| if (!listItemElement) | |
| return; | |
| if (!this._readyToUpdateSelection) { | |
| if (document.body.offsetWidth > 0) | |
| this._readyToUpdateSelection = true; | |
| else { | |
| return; | |
| } | |
| } | |
| if (!this.selectionElement) { | |
| this.selectionElement = document.createElement("div"); | |
| this.selectionElement.className = "selection selected"; | |
| listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild); | |
| } | |
| this.selectionElement.style.height = listItemElement.offsetHeight + "px"; | |
| }, | |
| onattach: function() | |
| { | |
| if (this._hovered) { | |
| this.updateSelection(); | |
| this.listItemElement.addStyleClass("hovered"); | |
| } | |
| this.updateTitle(); | |
| this._preventFollowingLinksOnDoubleClick(); | |
| this.listItemElement.draggable = true; | |
| }, | |
| _preventFollowingLinksOnDoubleClick: function() | |
| { | |
| var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link"); | |
| if (!links) | |
| return; | |
| for (var i = 0; i < links.length; ++i) | |
| links[i].preventFollowOnDoubleClick = true; | |
| }, | |
| onpopulate: function() | |
| { | |
| if (this.children.length || this._showInlineText(this.representedObject) || this._elementCloseTag) | |
| return; | |
| this.updateChildren(); | |
| }, | |
| updateChildren: function(fullRefresh) | |
| { | |
| if (this._elementCloseTag) | |
| return; | |
| this.representedObject.getChildNodes(this._updateChildren.bind(this, fullRefresh)); | |
| }, | |
| insertChildElement: function(child, index, closingTag) | |
| { | |
| var newElement = new WebInspector.ElementsTreeElement(child, closingTag); | |
| newElement.selectable = this.treeOutline._selectEnabled; | |
| this.insertChild(newElement, index); | |
| return newElement; | |
| }, | |
| moveChild: function(child, targetIndex) | |
| { | |
| var wasSelected = child.selected; | |
| this.removeChild(child); | |
| this.insertChild(child, targetIndex); | |
| if (wasSelected) | |
| child.select(); | |
| }, | |
| _updateChildren: function(fullRefresh) | |
| { | |
| if (this._updateChildrenInProgress || !this.treeOutline._visible) | |
| return; | |
| this._updateChildrenInProgress = true; | |
| var selectedNode = this.treeOutline.selectedDOMNode(); | |
| var originalScrollTop = 0; | |
| if (fullRefresh) { | |
| var treeOutlineContainerElement = this.treeOutline.element.parentNode; | |
| originalScrollTop = treeOutlineContainerElement.scrollTop; | |
| var selectedTreeElement = this.treeOutline.selectedTreeElement; | |
| if (selectedTreeElement && selectedTreeElement.hasAncestor(this)) | |
| this.select(); | |
| this.removeChildren(); | |
| } | |
| var treeElement = this; | |
| var treeChildIndex = 0; | |
| var elementToSelect; | |
| function updateChildrenOfNode(node) | |
| { | |
| var treeOutline = treeElement.treeOutline; | |
| var child = node.firstChild; | |
| while (child) { | |
| var currentTreeElement = treeElement.children[treeChildIndex]; | |
| if (!currentTreeElement || currentTreeElement.representedObject !== child) { | |
| var existingTreeElement = null; | |
| for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) { | |
| if (treeElement.children[i].representedObject === child) { | |
| existingTreeElement = treeElement.children[i]; | |
| break; | |
| } | |
| } | |
| if (existingTreeElement && existingTreeElement.parent === treeElement) { | |
| treeElement.moveChild(existingTreeElement, treeChildIndex); | |
| } else { | |
| if (treeChildIndex < treeElement.expandedChildrenLimit) { | |
| var newElement = treeElement.insertChildElement(child, treeChildIndex); | |
| if (child === selectedNode) | |
| elementToSelect = newElement; | |
| if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit) | |
| treeElement.expandedChildrenLimit++; | |
| } | |
| } | |
| } | |
| child = child.nextSibling; | |
| ++treeChildIndex; | |
| } | |
| } | |
| for (var i = (this.children.length - 1); i >= 0; --i) { | |
| var currentChild = this.children[i]; | |
| var currentNode = currentChild.representedObject; | |
| var currentParentNode = currentNode.parentNode; | |
| if (currentParentNode === this.representedObject) | |
| continue; | |
| var selectedTreeElement = this.treeOutline.selectedTreeElement; | |
| if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild))) | |
| this.select(); | |
| this.removeChildAtIndex(i); | |
| } | |
| updateChildrenOfNode(this.representedObject); | |
| this.adjustCollapsedRange(); | |
| var lastChild = this.children[this.children.length - 1]; | |
| if (this.representedObject.nodeType() == Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag)) | |
| this.insertChildElement(this.representedObject, this.children.length, true); | |
| if (fullRefresh && elementToSelect) { | |
| elementToSelect.select(); | |
| if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight) | |
| treeOutlineContainerElement.scrollTop = originalScrollTop; | |
| } | |
| delete this._updateChildrenInProgress; | |
| }, | |
| adjustCollapsedRange: function() | |
| { | |
| if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent) | |
| this.removeChild(this.expandAllButtonElement.__treeElement); | |
| const node = this.representedObject; | |
| if (!node.children) | |
| return; | |
| const childNodeCount = node.children.length; | |
| for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i) | |
| this.insertChildElement(node.children[i], i); | |
| const expandedChildCount = this.expandedChildCount; | |
| if (childNodeCount > this.expandedChildCount) { | |
| var targetButtonIndex = expandedChildCount; | |
| if (!this.expandAllButtonElement) { | |
| var button = document.createElement("button"); | |
| button.className = "show-all-nodes"; | |
| button.value = ""; | |
| var item = new TreeElement(button, null, false); | |
| item.selectable = false; | |
| item.expandAllButton = true; | |
| this.insertChild(item, targetButtonIndex); | |
| this.expandAllButtonElement = item.listItemElement.firstChild; | |
| this.expandAllButtonElement.__treeElement = item; | |
| this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false); | |
| } else if (!this.expandAllButtonElement.__treeElement.parent) | |
| this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex); | |
| this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)", childNodeCount - expandedChildCount); | |
| } else if (this.expandAllButtonElement) | |
| delete this.expandAllButtonElement; | |
| }, | |
| handleLoadAllChildren: function() | |
| { | |
| this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit); | |
| }, | |
| onexpand: function() | |
| { | |
| if (this._elementCloseTag) | |
| return; | |
| this.updateTitle(); | |
| this.treeOutline.updateSelection(); | |
| }, | |
| oncollapse: function() | |
| { | |
| if (this._elementCloseTag) | |
| return; | |
| this.updateTitle(); | |
| this.treeOutline.updateSelection(); | |
| }, | |
| onreveal: function() | |
| { | |
| if (this.listItemElement) { | |
| var tagSpans = this.listItemElement.getElementsByClassName("webkit-html-tag-name"); | |
| if (tagSpans.length) | |
| tagSpans[0].scrollIntoViewIfNeeded(false); | |
| else | |
| this.listItemElement.scrollIntoViewIfNeeded(false); | |
| } | |
| }, | |
| onselect: function(selectedByUser) | |
| { | |
| this.treeOutline.suppressRevealAndSelect = true; | |
| this.treeOutline.selectDOMNode(this.representedObject, selectedByUser); | |
| if (selectedByUser) | |
| WebInspector.domAgent.highlightDOMNode(this.representedObject.id); | |
| this.updateSelection(); | |
| this.treeOutline.suppressRevealAndSelect = false; | |
| return true; | |
| }, | |
| ondelete: function() | |
| { | |
| var startTagTreeElement = this.treeOutline.findTreeElement(this.representedObject); | |
| startTagTreeElement ? startTagTreeElement.remove() : this.remove(); | |
| return true; | |
| }, | |
| onenter: function() | |
| { | |
| if (this.treeOutline.editing) | |
| return false; | |
| this._startEditing(); | |
| return true; | |
| }, | |
| selectOnMouseDown: function(event) | |
| { | |
| TreeElement.prototype.selectOnMouseDown.call(this, event); | |
| if (this._editing) | |
| return; | |
| if (this.treeOutline._showInElementsPanelEnabled) { | |
| WebInspector.showPanel("elements"); | |
| this.treeOutline.selectDOMNode(this.representedObject, true); | |
| } | |
| if (event.detail >= 2) | |
| event.preventDefault(); | |
| }, | |
| ondblclick: function(event) | |
| { | |
| if (this._editing || this._elementCloseTag) | |
| return; | |
| if (this._startEditingTarget(event.target)) | |
| return; | |
| if (this.hasChildren && !this.expanded) | |
| this.expand(); | |
| }, | |
| _insertInLastAttributePosition: function(tag, node) | |
| { | |
| if (tag.getElementsByClassName("webkit-html-attribute").length > 0) | |
| tag.insertBefore(node, tag.lastChild); | |
| else { | |
| var nodeName = tag.textContent.match(/^<(.*?)>$/)[1]; | |
| tag.textContent = ''; | |
| tag.appendChild(document.createTextNode('<'+nodeName)); | |
| tag.appendChild(node); | |
| tag.appendChild(document.createTextNode('>')); | |
| } | |
| this.updateSelection(); | |
| }, | |
| _startEditingTarget: function(eventTarget) | |
| { | |
| if (this.treeOutline.selectedDOMNode() != this.representedObject) | |
| return; | |
| if (this.representedObject.nodeType() != Node.ELEMENT_NODE && this.representedObject.nodeType() != Node.TEXT_NODE) | |
| return false; | |
| var textNode = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-text-node"); | |
| if (textNode) | |
| return this._startEditingTextNode(textNode); | |
| var attribute = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-attribute"); | |
| if (attribute) | |
| return this._startEditingAttribute(attribute, eventTarget); | |
| var tagName = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-tag-name"); | |
| if (tagName) | |
| return this._startEditingTagName(tagName); | |
| var newAttribute = eventTarget.enclosingNodeOrSelfWithClass("add-attribute"); | |
| if (newAttribute) | |
| return this._addNewAttribute(); | |
| return false; | |
| }, | |
| _populateTagContextMenu: function(contextMenu, event) | |
| { | |
| var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute"); | |
| var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute"); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add attribute" : "Add Attribute"), this._addNewAttribute.bind(this)); | |
| if (attribute && !newAttribute) | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit attribute" : "Edit Attribute"), this._startEditingAttribute.bind(this, attribute, event.target)); | |
| contextMenu.appendSeparator(); | |
| if (this.treeOutline._setPseudoClassCallback) { | |
| var pseudoSubMenu = contextMenu.appendSubMenuItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Force element state" : "Force Element State")); | |
| this._populateForcedPseudoStateItems(pseudoSubMenu); | |
| contextMenu.appendSeparator(); | |
| } | |
| this._populateNodeContextMenu(contextMenu); | |
| this.treeOutline._populateContextMenu(contextMenu, this.representedObject); | |
| contextMenu.appendSeparator(); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Scroll into view" : "Scroll Into View"), this._scrollIntoView.bind(this)); | |
| }, | |
| _populateForcedPseudoStateItems: function(subMenu) | |
| { | |
| const pseudoClasses = ["active", "hover", "focus", "visited"]; | |
| var node = this.representedObject; | |
| var forcedPseudoState = (node ? node.getUserProperty("pseudoState") : null) || []; | |
| for (var i = 0; i < pseudoClasses.length; ++i) { | |
| var pseudoClassForced = forcedPseudoState.indexOf(pseudoClasses[i]) >= 0; | |
| subMenu.appendCheckboxItem(":" + pseudoClasses[i], this.treeOutline._setPseudoClassCallback.bind(null, node.id, pseudoClasses[i], !pseudoClassForced), pseudoClassForced, false); | |
| } | |
| }, | |
| _populateTextContextMenu: function(contextMenu, textNode) | |
| { | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit text" : "Edit Text"), this._startEditingTextNode.bind(this, textNode)); | |
| this._populateNodeContextMenu(contextMenu); | |
| }, | |
| _populateNodeContextMenu: function(contextMenu) | |
| { | |
| contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), this._editAsHTML.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString("Copy XPath"), this._copyXPath.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete node" : "Delete Node"), this.remove.bind(this)); | |
| }, | |
| _startEditing: function() | |
| { | |
| if (this.treeOutline.selectedDOMNode() !== this.representedObject) | |
| return; | |
| var listItem = this._listItemNode; | |
| if (this._canAddAttributes) { | |
| var attribute = listItem.getElementsByClassName("webkit-html-attribute")[0]; | |
| if (attribute) | |
| return this._startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]); | |
| return this._addNewAttribute(); | |
| } | |
| if (this.representedObject.nodeType() === Node.TEXT_NODE) { | |
| var textNode = listItem.getElementsByClassName("webkit-html-text-node")[0]; | |
| if (textNode) | |
| return this._startEditingTextNode(textNode); | |
| return; | |
| } | |
| }, | |
| _addNewAttribute: function() | |
| { | |
| var container = document.createElement("span"); | |
| this._buildAttributeDOM(container, " ", ""); | |
| var attr = container.firstChild; | |
| attr.style.marginLeft = "2px"; | |
| attr.style.marginRight = "2px"; | |
| var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0]; | |
| this._insertInLastAttributePosition(tag, attr); | |
| return this._startEditingAttribute(attr, attr); | |
| }, | |
| _triggerEditAttribute: function(attributeName) | |
| { | |
| var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name"); | |
| for (var i = 0, len = attributeElements.length; i < len; ++i) { | |
| if (attributeElements[i].textContent === attributeName) { | |
| for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) { | |
| if (elem.nodeType !== Node.ELEMENT_NODE) | |
| continue; | |
| if (elem.hasStyleClass("webkit-html-attribute-value")) | |
| return this._startEditingAttribute(elem.parentNode, elem); | |
| } | |
| } | |
| } | |
| }, | |
| _startEditingAttribute: function(attribute, elementForSelection) | |
| { | |
| if (WebInspector.isBeingEdited(attribute)) | |
| return true; | |
| var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0]; | |
| if (!attributeNameElement) | |
| return false; | |
| var attributeName = attributeNameElement.textContent; | |
| function removeZeroWidthSpaceRecursive(node) | |
| { | |
| if (node.nodeType === Node.TEXT_NODE) { | |
| node.nodeValue = node.nodeValue.replace(/\u200B/g, ""); | |
| return; | |
| } | |
| if (node.nodeType !== Node.ELEMENT_NODE) | |
| return; | |
| for (var child = node.firstChild; child; child = child.nextSibling) | |
| removeZeroWidthSpaceRecursive(child); | |
| } | |
| removeZeroWidthSpaceRecursive(attribute); | |
| var config = new WebInspector.EditingConfig(this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName); | |
| function handleKeyDownEvents(event) | |
| { | |
| var isMetaOrCtrl = WebInspector.isMac() ? | |
| event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey : | |
| event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey; | |
| if (isEnterKey(event) && (event.isMetaOrCtrlForTest || !config.multiline || isMetaOrCtrl)) | |
| return "commit"; | |
| else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B") | |
| return "cancel"; | |
| else if (event.keyIdentifier === "U+0009") | |
| return "move-" + (event.shiftKey ? "backward" : "forward"); | |
| else { | |
| WebInspector.handleElementValueModifications(event, attribute); | |
| return ""; | |
| } | |
| } | |
| config.customFinishHandler = handleKeyDownEvents.bind(this); | |
| this._editing = WebInspector.startEditing(attribute, config); | |
| window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1); | |
| return true; | |
| }, | |
| _startEditingTextNode: function(textNode) | |
| { | |
| if (WebInspector.isBeingEdited(textNode)) | |
| return true; | |
| var container = textNode.enclosingNodeOrSelfWithClass("webkit-html-text-node"); | |
| if (container) | |
| container.innerText = textNode._originalContent; | |
| var config = new WebInspector.EditingConfig(this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this)); | |
| this._editing = WebInspector.startEditing(textNode, config); | |
| window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1); | |
| return true; | |
| }, | |
| _startEditingTagName: function(tagNameElement) | |
| { | |
| if (!tagNameElement) { | |
| tagNameElement = this.listItemElement.getElementsByClassName("webkit-html-tag-name")[0]; | |
| if (!tagNameElement) | |
| return false; | |
| } | |
| var tagName = tagNameElement.textContent; | |
| if (WebInspector.ElementsTreeElement.EditTagBlacklist[tagName.toLowerCase()]) | |
| return false; | |
| if (WebInspector.isBeingEdited(tagNameElement)) | |
| return true; | |
| var closingTagElement = this._distinctClosingTagElement(); | |
| function keyupListener(event) | |
| { | |
| if (closingTagElement) | |
| closingTagElement.textContent = "</" + tagNameElement.textContent + ">"; | |
| } | |
| function editingComitted(element, newTagName) | |
| { | |
| tagNameElement.removeEventListener('keyup', keyupListener, false); | |
| this._tagNameEditingCommitted.apply(this, arguments); | |
| } | |
| function editingCancelled() | |
| { | |
| tagNameElement.removeEventListener('keyup', keyupListener, false); | |
| this._editingCancelled.apply(this, arguments); | |
| } | |
| tagNameElement.addEventListener('keyup', keyupListener, false); | |
| var config = new WebInspector.EditingConfig(editingComitted.bind(this), editingCancelled.bind(this), tagName); | |
| this._editing = WebInspector.startEditing(tagNameElement, config); | |
| window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1); | |
| return true; | |
| }, | |
| _startEditingAsHTML: function(commitCallback, error, initialValue) | |
| { | |
| if (error) | |
| return; | |
| if (this._htmlEditElement && WebInspector.isBeingEdited(this._htmlEditElement)) | |
| return; | |
| function consume(event) | |
| { | |
| if (event.eventPhase === Event.AT_TARGET) | |
| event.consume(true); | |
| } | |
| this._htmlEditElement = document.createElement("div"); | |
| this._htmlEditElement.className = "source-code elements-tree-editor"; | |
| this._htmlEditElement.textContent = initialValue; | |
| var child = this.listItemElement.firstChild; | |
| while (child) { | |
| child.style.display = "none"; | |
| child = child.nextSibling; | |
| } | |
| if (this._childrenListNode) | |
| this._childrenListNode.style.display = "none"; | |
| this.listItemElement.appendChild(this._htmlEditElement); | |
| this.treeOutline.childrenListElement.parentElement.addEventListener("mousedown", consume, false); | |
| this.updateSelection(); | |
| function commit() | |
| { | |
| commitCallback(initialValue, this._htmlEditElement.textContent); | |
| dispose.call(this); | |
| } | |
| function dispose() | |
| { | |
| this._editing = false; | |
| this.listItemElement.removeChild(this._htmlEditElement); | |
| delete this._htmlEditElement; | |
| if (this._childrenListNode) | |
| this._childrenListNode.style.removeProperty("display"); | |
| var child = this.listItemElement.firstChild; | |
| while (child) { | |
| child.style.removeProperty("display"); | |
| child = child.nextSibling; | |
| } | |
| this.treeOutline.childrenListElement.parentElement.removeEventListener("mousedown", consume, false); | |
| this.updateSelection(); | |
| } | |
| var config = new WebInspector.EditingConfig(commit.bind(this), dispose.bind(this)); | |
| config.setMultiline(true); | |
| this._editing = WebInspector.startEditing(this._htmlEditElement, config); | |
| }, | |
| _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection) | |
| { | |
| this._editing = false; | |
| var treeOutline = this.treeOutline; | |
| function moveToNextAttributeIfNeeded(error) | |
| { | |
| if (error) | |
| this._editingCancelled(element, attributeName); | |
| if (!moveDirection) | |
| return; | |
| treeOutline._updateModifiedNodes(); | |
| var attributes = this.representedObject.attributes(); | |
| for (var i = 0; i < attributes.length; ++i) { | |
| if (attributes[i].name !== attributeName) | |
| continue; | |
| if (moveDirection === "backward") { | |
| if (i === 0) | |
| this._startEditingTagName(); | |
| else | |
| this._triggerEditAttribute(attributes[i - 1].name); | |
| } else { | |
| if (i === attributes.length - 1) | |
| this._addNewAttribute(); | |
| else | |
| this._triggerEditAttribute(attributes[i + 1].name); | |
| } | |
| return; | |
| } | |
| if (moveDirection === "backward") { | |
| if (newText === " ") { | |
| if (attributes.length > 0) | |
| this._triggerEditAttribute(attributes[attributes.length - 1].name); | |
| } else { | |
| if (attributes.length > 1) | |
| this._triggerEditAttribute(attributes[attributes.length - 2].name); | |
| } | |
| } else if (moveDirection === "forward") { | |
| if (!/^\s*$/.test(newText)) | |
| this._addNewAttribute(); | |
| else | |
| this._startEditingTagName(); | |
| } | |
| } | |
| if (oldText !== newText) | |
| this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this)); | |
| else | |
| moveToNextAttributeIfNeeded.call(this); | |
| }, | |
| _tagNameEditingCommitted: function(element, newText, oldText, tagName, moveDirection) | |
| { | |
| this._editing = false; | |
| var self = this; | |
| function cancel() | |
| { | |
| var closingTagElement = self._distinctClosingTagElement(); | |
| if (closingTagElement) | |
| closingTagElement.textContent = "</" + tagName + ">"; | |
| self._editingCancelled(element, tagName); | |
| moveToNextAttributeIfNeeded.call(self); | |
| } | |
| function moveToNextAttributeIfNeeded() | |
| { | |
| if (moveDirection !== "forward") { | |
| this._addNewAttribute(); | |
| return; | |
| } | |
| var attributes = this.representedObject.attributes(); | |
| if (attributes.length > 0) | |
| this._triggerEditAttribute(attributes[0].name); | |
| else | |
| this._addNewAttribute(); | |
| } | |
| newText = newText.trim(); | |
| if (newText === oldText) { | |
| cancel(); | |
| return; | |
| } | |
| var treeOutline = this.treeOutline; | |
| var wasExpanded = this.expanded; | |
| function changeTagNameCallback(error, nodeId) | |
| { | |
| if (error || !nodeId) { | |
| cancel(); | |
| return; | |
| } | |
| var newTreeItem = treeOutline._selectNodeAfterEdit(null, wasExpanded, error, nodeId); | |
| moveToNextAttributeIfNeeded.call(newTreeItem); | |
| } | |
| this.representedObject.setNodeName(newText, changeTagNameCallback); | |
| }, | |
| _textNodeEditingCommitted: function(element, newText) | |
| { | |
| this._editing = false; | |
| var textNode; | |
| if (this.representedObject.nodeType() === Node.ELEMENT_NODE) { | |
| textNode = this.representedObject.firstChild; | |
| } else if (this.representedObject.nodeType() == Node.TEXT_NODE) | |
| textNode = this.representedObject; | |
| textNode.setNodeValue(newText, this.updateTitle.bind(this)); | |
| }, | |
| _editingCancelled: function(element, context) | |
| { | |
| this._editing = false; | |
| this.updateTitle(); | |
| }, | |
| _distinctClosingTagElement: function() | |
| { | |
| if (this.expanded) { | |
| var closers = this._childrenListNode.querySelectorAll(".close"); | |
| return closers[closers.length-1]; | |
| } | |
| var tags = this.listItemElement.getElementsByClassName("webkit-html-tag"); | |
| return (tags.length === 1 ? null : tags[tags.length-1]); | |
| }, | |
| updateTitle: function(onlySearchQueryChanged) | |
| { | |
| if (this._editing) | |
| return; | |
| if (onlySearchQueryChanged) { | |
| if (this._highlightResult) | |
| this._updateSearchHighlight(false); | |
| } else { | |
| var highlightElement = document.createElement("span"); | |
| highlightElement.className = "highlight"; | |
| highlightElement.appendChild(this._nodeTitleInfo(WebInspector.linkifyURLAsNode).titleDOM); | |
| this.title = highlightElement; | |
| this._updateDecorations(); | |
| delete this._highlightResult; | |
| } | |
| delete this.selectionElement; | |
| if (this.selected) | |
| this.updateSelection(); | |
| this._preventFollowingLinksOnDoubleClick(); | |
| this._highlightSearchResults(); | |
| }, | |
| _createDecoratorElement: function() | |
| { | |
| var node = this.representedObject; | |
| var decoratorMessages = []; | |
| var parentDecoratorMessages = []; | |
| for (var i = 0; i < this.treeOutline._nodeDecorators.length; ++i) { | |
| var decorator = this.treeOutline._nodeDecorators[i]; | |
| var message = decorator.decorate(node); | |
| if (message) { | |
| decoratorMessages.push(message); | |
| continue; | |
| } | |
| if (this.expanded || this._elementCloseTag) | |
| continue; | |
| message = decorator.decorateAncestor(node); | |
| if (message) | |
| parentDecoratorMessages.push(message) | |
| } | |
| if (!decoratorMessages.length && !parentDecoratorMessages.length) | |
| return null; | |
| var decoratorElement = document.createElement("div"); | |
| decoratorElement.addStyleClass("elements-gutter-decoration"); | |
| if (!decoratorMessages.length) | |
| decoratorElement.addStyleClass("elements-has-decorated-children"); | |
| decoratorElement.title = decoratorMessages.concat(parentDecoratorMessages).join("\n"); | |
| return decoratorElement; | |
| }, | |
| _updateDecorations: function() | |
| { | |
| if (this._decoratorElement && this._decoratorElement.parentElement) | |
| this._decoratorElement.parentElement.removeChild(this._decoratorElement); | |
| this._decoratorElement = this._createDecoratorElement(); | |
| if (this._decoratorElement && this.listItemElement) | |
| this.listItemElement.insertBefore(this._decoratorElement, this.listItemElement.firstChild); | |
| }, | |
| _buildAttributeDOM: function(parentElement, name, value, node, linkify) | |
| { | |
| var hasText = (value.length > 0); | |
| var attrSpanElement = parentElement.createChild("span", "webkit-html-attribute"); | |
| var attrNameElement = attrSpanElement.createChild("span", "webkit-html-attribute-name"); | |
| attrNameElement.textContent = name; | |
| if (hasText) | |
| attrSpanElement.appendChild(document.createTextNode("=\u200B\"")); | |
| if (linkify && (name === "src" || name === "href")) { | |
| var rewrittenHref = node.resolveURL(value); | |
| value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); | |
| if (rewrittenHref === null) { | |
| var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value"); | |
| attrValueElement.textContent = value; | |
| } else { | |
| if (value.startsWith("data:")) | |
| value = value.trimMiddle(60); | |
| attrSpanElement.appendChild(linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a")); | |
| } | |
| } else { | |
| value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); | |
| var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value"); | |
| attrValueElement.textContent = value; | |
| } | |
| if (hasText) | |
| attrSpanElement.appendChild(document.createTextNode("\"")); | |
| }, | |
| _buildTagDOM: function(parentElement, tagName, isClosingTag, isDistinctTreeElement, linkify) | |
| { | |
| var node = this.representedObject; | |
| var classes = [ "webkit-html-tag" ]; | |
| if (isClosingTag && isDistinctTreeElement) | |
| classes.push("close"); | |
| if (node.isInShadowTree()) | |
| classes.push("shadow"); | |
| var tagElement = parentElement.createChild("span", classes.join(" ")); | |
| tagElement.appendChild(document.createTextNode("<")); | |
| var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name"); | |
| tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName; | |
| if (!isClosingTag && node.hasAttributes()) { | |
| var attributes = node.attributes(); | |
| for (var i = 0; i < attributes.length; ++i) { | |
| var attr = attributes[i]; | |
| tagElement.appendChild(document.createTextNode(" ")); | |
| this._buildAttributeDOM(tagElement, attr.name, attr.value, node, linkify); | |
| } | |
| } | |
| tagElement.appendChild(document.createTextNode(">")); | |
| parentElement.appendChild(document.createTextNode("\u200B")); | |
| }, | |
| _convertWhitespaceToEntities: function(text) | |
| { | |
| var result = ""; | |
| var lastIndexAfterEntity = 0; | |
| var charToEntity = WebInspector.ElementsTreeOutline.MappedCharToEntity; | |
| for (var i = 0, size = text.length; i < size; ++i) { | |
| var char = text.charAt(i); | |
| if (charToEntity[char]) { | |
| result += text.substring(lastIndexAfterEntity, i) + "&" + charToEntity[char] + ";"; | |
| lastIndexAfterEntity = i + 1; | |
| } | |
| } | |
| if (result) { | |
| result += text.substring(lastIndexAfterEntity); | |
| return result; | |
| } | |
| return text; | |
| }, | |
| _nodeTitleInfo: function(linkify) | |
| { | |
| var node = this.representedObject; | |
| var info = {titleDOM: document.createDocumentFragment(), hasChildren: this.hasChildren}; | |
| switch (node.nodeType()) { | |
| case Node.ATTRIBUTE_NODE: | |
| var value = node.value || "\u200B"; | |
| this._buildAttributeDOM(info.titleDOM, node.name, value); | |
| break; | |
| case Node.ELEMENT_NODE: | |
| var tagName = node.nodeNameInCorrectCase(); | |
| if (this._elementCloseTag) { | |
| this._buildTagDOM(info.titleDOM, tagName, true, true); | |
| info.hasChildren = false; | |
| break; | |
| } | |
| this._buildTagDOM(info.titleDOM, tagName, false, false, linkify); | |
| var textChild = this._singleTextChild(node); | |
| var showInlineText = textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength; | |
| if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) { | |
| if (this.hasChildren) { | |
| var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node bogus"); | |
| textNodeElement.textContent = "\u2026"; | |
| info.titleDOM.appendChild(document.createTextNode("\u200B")); | |
| } | |
| this._buildTagDOM(info.titleDOM, tagName, true, false); | |
| } | |
| if (showInlineText) { | |
| var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); | |
| textNodeElement.textContent = this._convertWhitespaceToEntities(textChild.nodeValue()); | |
| textNodeElement._originalContent = textChild.nodeValue(); | |
| info.titleDOM.appendChild(document.createTextNode("\u200B")); | |
| this._buildTagDOM(info.titleDOM, tagName, true, false); | |
| info.hasChildren = false; | |
| } | |
| break; | |
| case Node.TEXT_NODE: | |
| if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") { | |
| var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-js-node"); | |
| newNode.textContent = node.nodeValue(); | |
| var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript", true); | |
| javascriptSyntaxHighlighter.syntaxHighlightNode(newNode); | |
| } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") { | |
| var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-css-node"); | |
| newNode.textContent = node.nodeValue(); | |
| var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css", true); | |
| cssSyntaxHighlighter.syntaxHighlightNode(newNode); | |
| } else { | |
| info.titleDOM.appendChild(document.createTextNode("\"")); | |
| var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); | |
| textNodeElement.textContent = this._convertWhitespaceToEntities(node.nodeValue()); | |
| textNodeElement._originalContent = node.nodeValue(); | |
| info.titleDOM.appendChild(document.createTextNode("\"")); | |
| } | |
| break; | |
| case Node.COMMENT_NODE: | |
| var commentElement = info.titleDOM.createChild("span", "webkit-html-comment"); | |
| commentElement.appendChild(document.createTextNode("<!--" + node.nodeValue() + "-->")); | |
| break; | |
| case Node.DOCUMENT_TYPE_NODE: | |
| var docTypeElement = info.titleDOM.createChild("span", "webkit-html-doctype"); | |
| docTypeElement.appendChild(document.createTextNode("<!DOCTYPE " + node.nodeName())); | |
| if (node.publicId) { | |
| docTypeElement.appendChild(document.createTextNode(" PUBLIC \"" + node.publicId + "\"")); | |
| if (node.systemId) | |
| docTypeElement.appendChild(document.createTextNode(" \"" + node.systemId + "\"")); | |
| } else if (node.systemId) | |
| docTypeElement.appendChild(document.createTextNode(" SYSTEM \"" + node.systemId + "\"")); | |
| if (node.internalSubset) | |
| docTypeElement.appendChild(document.createTextNode(" [" + node.internalSubset + "]")); | |
| docTypeElement.appendChild(document.createTextNode(">")); | |
| break; | |
| case Node.CDATA_SECTION_NODE: | |
| var cdataElement = info.titleDOM.createChild("span", "webkit-html-text-node"); | |
| cdataElement.appendChild(document.createTextNode("<![CDATA[" + node.nodeValue() + "]]>")); | |
| break; | |
| case Node.DOCUMENT_FRAGMENT_NODE: | |
| var fragmentElement = info.titleDOM.createChild("span", "webkit-html-fragment"); | |
| fragmentElement.textContent = node.nodeNameInCorrectCase().collapseWhitespace(); | |
| if (node.isInShadowTree()) | |
| fragmentElement.addStyleClass("shadow"); | |
| break; | |
| default: | |
| info.titleDOM.appendChild(document.createTextNode(node.nodeNameInCorrectCase().collapseWhitespace())); | |
| } | |
| return info; | |
| }, | |
| _singleTextChild: function(node) | |
| { | |
| if (!node) | |
| return null; | |
| var firstChild = node.firstChild; | |
| if (!firstChild || firstChild.nodeType() !== Node.TEXT_NODE) | |
| return null; | |
| var sibling = firstChild.nextSibling; | |
| return sibling ? null : firstChild; | |
| }, | |
| _showInlineText: function(node) | |
| { | |
| if (node.nodeType() === Node.ELEMENT_NODE) { | |
| var textChild = this._singleTextChild(node); | |
| if (textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength) | |
| return true; | |
| } | |
| return false; | |
| }, | |
| remove: function() | |
| { | |
| var parentElement = this.parent; | |
| if (!parentElement) | |
| return; | |
| var self = this; | |
| function removeNodeCallback(error, removedNodeId) | |
| { | |
| if (error) | |
| return; | |
| parentElement.removeChild(self); | |
| parentElement.adjustCollapsedRange(); | |
| } | |
| if (!this.representedObject.parentNode || this.representedObject.parentNode.nodeType() === Node.DOCUMENT_NODE) | |
| return; | |
| this.representedObject.removeNode(removeNodeCallback); | |
| }, | |
| _editAsHTML: function() | |
| { | |
| var treeOutline = this.treeOutline; | |
| var node = this.representedObject; | |
| var parentNode = node.parentNode; | |
| var index = node.index; | |
| var wasExpanded = this.expanded; | |
| function selectNode(error, nodeId) | |
| { | |
| if (error) | |
| return; | |
| treeOutline._updateModifiedNodes(); | |
| var newNode = parentNode ? parentNode.children[index] || parentNode : null; | |
| if (!newNode) | |
| return; | |
| treeOutline.selectDOMNode(newNode, true); | |
| if (wasExpanded) { | |
| var newTreeItem = treeOutline.findTreeElement(newNode); | |
| if (newTreeItem) | |
| newTreeItem.expand(); | |
| } | |
| } | |
| function commitChange(initialValue, value) | |
| { | |
| if (initialValue !== value) | |
| node.setOuterHTML(value, selectNode); | |
| else | |
| return; | |
| } | |
| node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange)); | |
| }, | |
| _copyHTML: function() | |
| { | |
| this.representedObject.copyNode(); | |
| }, | |
| _copyXPath: function() | |
| { | |
| this.representedObject.copyXPath(true); | |
| }, | |
| _highlightSearchResults: function() | |
| { | |
| if (!this._searchQuery || !this._searchHighlightsVisible) | |
| return; | |
| if (this._highlightResult) { | |
| this._updateSearchHighlight(true); | |
| return; | |
| } | |
| var text = this.listItemElement.textContent; | |
| var regexObject = createPlainTextSearchRegex(this._searchQuery, "gi"); | |
| var offset = 0; | |
| var match = regexObject.exec(text); | |
| var matchRanges = []; | |
| while (match) { | |
| matchRanges.push({ offset: match.index, length: match[0].length }); | |
| match = regexObject.exec(text); | |
| } | |
| if (!matchRanges.length) | |
| matchRanges.push({ offset: 0, length: text.length }); | |
| this._highlightResult = []; | |
| WebInspector.highlightSearchResults(this.listItemElement, matchRanges, this._highlightResult); | |
| }, | |
| _scrollIntoView: function() | |
| { | |
| function scrollIntoViewCallback(object) | |
| { | |
| function scrollIntoView() | |
| { | |
| this.scrollIntoViewIfNeeded(true); | |
| } | |
| if (object) | |
| object.callFunction(scrollIntoView); | |
| } | |
| var node = this.representedObject; | |
| WebInspector.RemoteObject.resolveNode(node, "", scrollIntoViewCallback); | |
| } | |
| } | |
| WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.ElementsTreeUpdater = function(treeOutline) | |
| { | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeInserted, this._nodeInserted, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesUpdated, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesUpdated, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.CharacterDataModified, this._characterDataModified, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this); | |
| this._treeOutline = treeOutline; | |
| this._recentlyModifiedNodes = new Map(); | |
| } | |
| WebInspector.ElementsTreeUpdater.prototype = { | |
| _nodeModified: function(node, isUpdated, parentNode) | |
| { | |
| if (this._treeOutline._visible) | |
| this._updateModifiedNodesSoon(); | |
| var entry = this._recentlyModifiedNodes.get(node); | |
| if (!entry) { | |
| entry = new WebInspector.ElementsTreeUpdater.UpdateEntry(isUpdated, parentNode); | |
| this._recentlyModifiedNodes.put(node, entry); | |
| return; | |
| } | |
| entry.isUpdated |= isUpdated; | |
| if (parentNode) | |
| entry.parent = parentNode; | |
| }, | |
| _documentUpdated: function(event) | |
| { | |
| var inspectedRootDocument = event.data; | |
| this._reset(); | |
| if (!inspectedRootDocument) | |
| return; | |
| this._treeOutline.rootDOMNode = inspectedRootDocument; | |
| }, | |
| _attributesUpdated: function(event) | |
| { | |
| this._nodeModified(event.data.node, true); | |
| }, | |
| _characterDataModified: function(event) | |
| { | |
| this._nodeModified(event.data, true); | |
| }, | |
| _nodeInserted: function(event) | |
| { | |
| this._nodeModified(event.data, false, event.data.parentNode); | |
| }, | |
| _nodeRemoved: function(event) | |
| { | |
| this._nodeModified(event.data.node, false, event.data.parent); | |
| }, | |
| _childNodeCountUpdated: function(event) | |
| { | |
| var treeElement = this._treeOutline.findTreeElement(event.data); | |
| if (treeElement) | |
| treeElement.hasChildren = event.data.hasChildNodes(); | |
| }, | |
| _updateModifiedNodesSoon: function() | |
| { | |
| if (this._updateModifiedNodesTimeout) | |
| return; | |
| this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 50); | |
| }, | |
| _updateModifiedNodes: function() | |
| { | |
| if (this._updateModifiedNodesTimeout) { | |
| clearTimeout(this._updateModifiedNodesTimeout); | |
| delete this._updateModifiedNodesTimeout; | |
| } | |
| var updatedParentTreeElements = []; | |
| var hidePanelWhileUpdating = this._recentlyModifiedNodes.size() > 10; | |
| if (hidePanelWhileUpdating) { | |
| var treeOutlineContainerElement = this._treeOutline.element.parentNode; | |
| this._treeOutline.element.addStyleClass("hidden"); | |
| var originalScrollTop = treeOutlineContainerElement ? treeOutlineContainerElement.scrollTop : 0; | |
| } | |
| var keys = this._recentlyModifiedNodes.keys(); | |
| for (var i = 0, size = keys.length; i < size; ++i) { | |
| var node = keys[i]; | |
| var entry = this._recentlyModifiedNodes.get(node); | |
| var parent = entry.parent; | |
| if (parent === this._treeOutline._rootDOMNode) { | |
| this._treeOutline.update(); | |
| this._treeOutline.element.removeStyleClass("hidden"); | |
| return; | |
| } | |
| if (entry.isUpdated) { | |
| var nodeItem = this._treeOutline.findTreeElement(node); | |
| if (nodeItem) | |
| nodeItem.updateTitle(); | |
| } | |
| if (!parent) | |
| continue; | |
| var parentNodeItem = this._treeOutline.findTreeElement(parent); | |
| if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) { | |
| parentNodeItem.updateChildren(); | |
| parentNodeItem.alreadyUpdatedChildren = true; | |
| updatedParentTreeElements.push(parentNodeItem); | |
| } | |
| } | |
| for (var i = 0; i < updatedParentTreeElements.length; ++i) | |
| delete updatedParentTreeElements[i].alreadyUpdatedChildren; | |
| if (hidePanelWhileUpdating) { | |
| this._treeOutline.element.removeStyleClass("hidden"); | |
| if (originalScrollTop) | |
| treeOutlineContainerElement.scrollTop = originalScrollTop; | |
| this._treeOutline.updateSelection(); | |
| } | |
| this._recentlyModifiedNodes.clear(); | |
| }, | |
| _reset: function() | |
| { | |
| this._treeOutline.rootDOMNode = null; | |
| this._treeOutline.selectDOMNode(null, false); | |
| WebInspector.domAgent.hideDOMNodeHighlight(); | |
| this._recentlyModifiedNodes.clear(); | |
| } | |
| } | |
| WebInspector.ElementsTreeUpdater.UpdateEntry = function(isUpdated, parent) | |
| { | |
| this.isUpdated = isUpdated; | |
| if (parent) | |
| this.parent = parent; | |
| } | |
| WebInspector.DOMPresentationUtils = {} | |
| WebInspector.DOMPresentationUtils.decorateNodeLabel = function(node, parentElement) | |
| { | |
| var title = node.nodeNameInCorrectCase(); | |
| var nameElement = document.createElement("span"); | |
| nameElement.textContent = title; | |
| parentElement.appendChild(nameElement); | |
| var idAttribute = node.getAttribute("id"); | |
| if (idAttribute) { | |
| var idElement = document.createElement("span"); | |
| parentElement.appendChild(idElement); | |
| var part = "#" + idAttribute; | |
| title += part; | |
| idElement.appendChild(document.createTextNode(part)); | |
| nameElement.className = "extra"; | |
| } | |
| var classAttribute = node.getAttribute("class"); | |
| if (classAttribute) { | |
| var classes = classAttribute.split(/\s+/); | |
| var foundClasses = {}; | |
| if (classes.length) { | |
| var classesElement = document.createElement("span"); | |
| classesElement.className = "extra"; | |
| parentElement.appendChild(classesElement); | |
| for (var i = 0; i < classes.length; ++i) { | |
| var className = classes[i]; | |
| if (className && !(className in foundClasses)) { | |
| var part = "." + className; | |
| title += part; | |
| classesElement.appendChild(document.createTextNode(part)); | |
| foundClasses[className] = true; | |
| } | |
| } | |
| } | |
| } | |
| parentElement.title = title; | |
| } | |
| WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node) | |
| { | |
| var link = document.createElement("span"); | |
| link.className = "node-link"; | |
| WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link); | |
| link.addEventListener("click", WebInspector.domAgent.inspectElement.bind(WebInspector.domAgent, node.id), false); | |
| link.addEventListener("mouseover", WebInspector.domAgent.highlightDOMNode.bind(WebInspector.domAgent, node.id, ""), false); | |
| link.addEventListener("mouseout", WebInspector.domAgent.hideDOMNodeHighlight.bind(WebInspector.domAgent), false); | |
| return link; | |
| } | |
| WebInspector.DOMPresentationUtils.linkifyNodeById = function(nodeId) | |
| { | |
| var node = WebInspector.domAgent.nodeForId(nodeId); | |
| if (!node) | |
| return document.createTextNode(WebInspector.UIString("<node>")); | |
| return WebInspector.DOMPresentationUtils.linkifyNodeReference(node); | |
| } | |
| WebInspector.DOMPresentationUtils.buildImagePreviewContents = function(imageURL, showDimensions, userCallback, precomputedDimensions) | |
| { | |
| var resource = WebInspector.resourceTreeModel.resourceForURL(imageURL); | |
| if (!resource) { | |
| userCallback(); | |
| return; | |
| } | |
| var imageElement = document.createElement("img"); | |
| imageElement.addEventListener("load", buildContent, false); | |
| imageElement.addEventListener("error", errorCallback, false); | |
| resource.populateImageSource(imageElement); | |
| function errorCallback() | |
| { | |
| userCallback(); | |
| } | |
| function buildContent() | |
| { | |
| var container = document.createElement("table"); | |
| container.className = "image-preview-container"; | |
| var naturalWidth = precomputedDimensions ? precomputedDimensions.naturalWidth : imageElement.naturalWidth; | |
| var naturalHeight = precomputedDimensions ? precomputedDimensions.naturalHeight : imageElement.naturalHeight; | |
| var offsetWidth = precomputedDimensions ? precomputedDimensions.offsetWidth : naturalWidth; | |
| var offsetHeight = precomputedDimensions ? precomputedDimensions.offsetHeight : naturalHeight; | |
| var description; | |
| if (showDimensions) { | |
| if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) | |
| description = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight); | |
| else | |
| description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); | |
| } | |
| container.createChild("tr").createChild("td", "image-container").appendChild(imageElement); | |
| if (description) | |
| container.createChild("tr").createChild("td").createChild("span", "description").textContent = description; | |
| userCallback(container); | |
| } | |
| } | |
| WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasChildren) | |
| { | |
| TreeElement.call(this, title.escapeHTML(), representedObject || {}, hasChildren); | |
| this.expand(); | |
| } | |
| WebInspector.SidebarSectionTreeElement.prototype = { | |
| selectable: false, | |
| collapse: function() | |
| { | |
| }, | |
| get smallChildren() | |
| { | |
| return this._smallChildren; | |
| }, | |
| set smallChildren(x) | |
| { | |
| if (this._smallChildren === x) | |
| return; | |
| this._smallChildren = x; | |
| if (this._smallChildren) | |
| this._childrenListNode.addStyleClass("small"); | |
| else | |
| this._childrenListNode.removeStyleClass("small"); | |
| }, | |
| onattach: function() | |
| { | |
| this._listItemNode.addStyleClass("sidebar-tree-section"); | |
| }, | |
| onreveal: function() | |
| { | |
| if (this.listItemElement) | |
| this.listItemElement.scrollIntoViewIfNeeded(false); | |
| } | |
| } | |
| WebInspector.SidebarSectionTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.SidebarTreeElement = function(className, title, subtitle, representedObject, hasChildren) | |
| { | |
| TreeElement.call(this, "", representedObject, hasChildren); | |
| if (hasChildren) { | |
| this.disclosureButton = document.createElement("button"); | |
| this.disclosureButton.className = "disclosure-button"; | |
| } | |
| if (!this.iconElement) { | |
| this.iconElement = document.createElement("img"); | |
| this.iconElement.className = "icon"; | |
| } | |
| this.statusElement = document.createElement("div"); | |
| this.statusElement.className = "status"; | |
| this.titlesElement = document.createElement("div"); | |
| this.titlesElement.className = "titles"; | |
| this.titleElement = document.createElement("span"); | |
| this.titleElement.className = "title"; | |
| this.titlesElement.appendChild(this.titleElement); | |
| this.subtitleElement = document.createElement("span"); | |
| this.subtitleElement.className = "subtitle"; | |
| this.titlesElement.appendChild(this.subtitleElement); | |
| this.className = className; | |
| this.mainTitle = title; | |
| this.subtitle = subtitle; | |
| } | |
| WebInspector.SidebarTreeElement.prototype = { | |
| get small() | |
| { | |
| return this._small; | |
| }, | |
| set small(x) | |
| { | |
| this._small = x; | |
| if (this._listItemNode) { | |
| if (this._small) | |
| this._listItemNode.addStyleClass("small"); | |
| else | |
| this._listItemNode.removeStyleClass("small"); | |
| } | |
| }, | |
| get mainTitle() | |
| { | |
| return this._mainTitle; | |
| }, | |
| set mainTitle(x) | |
| { | |
| this._mainTitle = x; | |
| this.refreshTitles(); | |
| }, | |
| get subtitle() | |
| { | |
| return this._subtitle; | |
| }, | |
| set subtitle(x) | |
| { | |
| this._subtitle = x; | |
| this.refreshTitles(); | |
| }, | |
| get bubbleText() | |
| { | |
| return this._bubbleText; | |
| }, | |
| set bubbleText(x) | |
| { | |
| if (!this.bubbleElement) { | |
| this.bubbleElement = document.createElement("div"); | |
| this.bubbleElement.className = "bubble"; | |
| this.statusElement.appendChild(this.bubbleElement); | |
| } | |
| this._bubbleText = x; | |
| this.bubbleElement.textContent = x; | |
| }, | |
| set wait(x) | |
| { | |
| if (x) | |
| this._listItemNode.addStyleClass("wait"); | |
| else | |
| this._listItemNode.removeStyleClass("wait"); | |
| }, | |
| refreshTitles: function() | |
| { | |
| var mainTitle = this.mainTitle; | |
| if (this.titleElement.textContent !== mainTitle) | |
| this.titleElement.textContent = mainTitle; | |
| var subtitle = this.subtitle; | |
| if (subtitle) { | |
| if (this.subtitleElement.textContent !== subtitle) | |
| this.subtitleElement.textContent = subtitle; | |
| this.titlesElement.removeStyleClass("no-subtitle"); | |
| } else { | |
| this.subtitleElement.textContent = ""; | |
| this.titlesElement.addStyleClass("no-subtitle"); | |
| } | |
| }, | |
| isEventWithinDisclosureTriangle: function(event) | |
| { | |
| return event.target === this.disclosureButton; | |
| }, | |
| onattach: function() | |
| { | |
| this._listItemNode.addStyleClass("sidebar-tree-item"); | |
| if (this.className) | |
| this._listItemNode.addStyleClass(this.className); | |
| if (this.small) | |
| this._listItemNode.addStyleClass("small"); | |
| if (this.hasChildren && this.disclosureButton) | |
| this._listItemNode.appendChild(this.disclosureButton); | |
| this._listItemNode.appendChild(this.iconElement); | |
| this._listItemNode.appendChild(this.statusElement); | |
| this._listItemNode.appendChild(this.titlesElement); | |
| }, | |
| onreveal: function() | |
| { | |
| if (this._listItemNode) | |
| this._listItemNode.scrollIntoViewIfNeeded(false); | |
| } | |
| } | |
| WebInspector.SidebarTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.Section = function(title, subtitle) | |
| { | |
| this.element = document.createElement("div"); | |
| this.element.className = "section"; | |
| this.element._section = this; | |
| this.headerElement = document.createElement("div"); | |
| this.headerElement.className = "header"; | |
| this.titleElement = document.createElement("div"); | |
| this.titleElement.className = "title"; | |
| this.subtitleElement = document.createElement("div"); | |
| this.subtitleElement.className = "subtitle"; | |
| this.headerElement.appendChild(this.subtitleElement); | |
| this.headerElement.appendChild(this.titleElement); | |
| this.headerElement.addEventListener("click", this.handleClick.bind(this), false); | |
| this.element.appendChild(this.headerElement); | |
| this.title = title; | |
| this.subtitle = subtitle; | |
| this._expanded = false; | |
| } | |
| WebInspector.Section.prototype = { | |
| get title() | |
| { | |
| return this._title; | |
| }, | |
| set title(x) | |
| { | |
| if (this._title === x) | |
| return; | |
| this._title = x; | |
| if (x instanceof Node) { | |
| this.titleElement.removeChildren(); | |
| this.titleElement.appendChild(x); | |
| } else | |
| this.titleElement.textContent = x; | |
| }, | |
| get subtitle() | |
| { | |
| return this._subtitle; | |
| }, | |
| set subtitle(x) | |
| { | |
| if (this._subtitle === x) | |
| return; | |
| this._subtitle = x; | |
| this.subtitleElement.textContent = x; | |
| }, | |
| get subtitleAsTextForTest() | |
| { | |
| var result = this.subtitleElement.textContent; | |
| var child = this.subtitleElement.querySelector("[data-uncopyable]"); | |
| if (child) { | |
| var linkData = child.getAttribute("data-uncopyable"); | |
| if (linkData) | |
| result += linkData; | |
| } | |
| return result; | |
| }, | |
| get expanded() | |
| { | |
| return this._expanded; | |
| }, | |
| set expanded(x) | |
| { | |
| if (x) | |
| this.expand(); | |
| else | |
| this.collapse(); | |
| }, | |
| get populated() | |
| { | |
| return this._populated; | |
| }, | |
| set populated(x) | |
| { | |
| this._populated = x; | |
| if (!x && this._expanded) { | |
| this.onpopulate(); | |
| this._populated = true; | |
| } | |
| }, | |
| onpopulate: function() | |
| { | |
| }, | |
| get firstSibling() | |
| { | |
| var parent = this.element.parentElement; | |
| if (!parent) | |
| return null; | |
| var childElement = parent.firstChild; | |
| while (childElement) { | |
| if (childElement._section) | |
| return childElement._section; | |
| childElement = childElement.nextSibling; | |
| } | |
| return null; | |
| }, | |
| get lastSibling() | |
| { | |
| var parent = this.element.parentElement; | |
| if (!parent) | |
| return null; | |
| var childElement = parent.lastChild; | |
| while (childElement) { | |
| if (childElement._section) | |
| return childElement._section; | |
| childElement = childElement.previousSibling; | |
| } | |
| return null; | |
| }, | |
| get nextSibling() | |
| { | |
| var curElement = this.element; | |
| do { | |
| curElement = curElement.nextSibling; | |
| } while (curElement && !curElement._section); | |
| return curElement ? curElement._section : null; | |
| }, | |
| get previousSibling() | |
| { | |
| var curElement = this.element; | |
| do { | |
| curElement = curElement.previousSibling; | |
| } while (curElement && !curElement._section); | |
| return curElement ? curElement._section : null; | |
| }, | |
| expand: function() | |
| { | |
| if (this._expanded) | |
| return; | |
| this._expanded = true; | |
| this.element.addStyleClass("expanded"); | |
| if (!this._populated) { | |
| this.onpopulate(); | |
| this._populated = true; | |
| } | |
| }, | |
| collapse: function() | |
| { | |
| if (!this._expanded) | |
| return; | |
| this._expanded = false; | |
| this.element.removeStyleClass("expanded"); | |
| }, | |
| toggleExpanded: function() | |
| { | |
| this.expanded = !this.expanded; | |
| }, | |
| handleClick: function(event) | |
| { | |
| this.toggleExpanded(); | |
| event.consume(); | |
| } | |
| } | |
| WebInspector.PropertiesSection = function(title, subtitle) | |
| { | |
| WebInspector.Section.call(this, title, subtitle); | |
| this.headerElement.addStyleClass("monospace"); | |
| this.propertiesElement = document.createElement("ol"); | |
| this.propertiesElement.className = "properties properties-tree monospace"; | |
| this.propertiesTreeOutline = new TreeOutline(this.propertiesElement, true); | |
| this.propertiesTreeOutline.setFocusable(false); | |
| this.propertiesTreeOutline.section = this; | |
| this.element.appendChild(this.propertiesElement); | |
| } | |
| WebInspector.PropertiesSection.prototype.__proto__ = WebInspector.Section.prototype; | |
| WebInspector.RemoteObject = function(objectId, type, subtype, value, description, preview) | |
| { | |
| this._type = type; | |
| this._subtype = subtype; | |
| if (objectId) { | |
| this._objectId = objectId; | |
| this._description = description; | |
| this._hasChildren = true; | |
| this._preview = preview; | |
| } else { | |
| console.assert(type !== "object" || value === null); | |
| this._description = description || (value + ""); | |
| this._hasChildren = false; | |
| this.value = value; | |
| } | |
| } | |
| WebInspector.RemoteObject.fromPrimitiveValue = function(value) | |
| { | |
| return new WebInspector.RemoteObject(undefined, typeof value, undefined, value); | |
| } | |
| WebInspector.RemoteObject.fromLocalObject = function(value) | |
| { | |
| return new WebInspector.LocalJSONObject(value); | |
| } | |
| WebInspector.RemoteObject.resolveNode = function(node, objectGroup, callback) | |
| { | |
| function mycallback(error, object) | |
| { | |
| if (!callback) | |
| return; | |
| if (error || !object) | |
| callback(null); | |
| else | |
| callback(WebInspector.RemoteObject.fromPayload(object)); | |
| } | |
| DOMAgent.resolveNode(node.id, objectGroup, mycallback); | |
| } | |
| WebInspector.RemoteObject.fromPayload = function(payload) | |
| { | |
| console.assert(typeof payload === "object", "Remote object payload should only be an object"); | |
| return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description, payload.preview); | |
| } | |
| WebInspector.RemoteObject.type = function(remoteObject) | |
| { | |
| if (remoteObject === null) | |
| return "null"; | |
| var type = typeof remoteObject; | |
| if (type !== "object" && type !== "function") | |
| return type; | |
| return remoteObject.type; | |
| } | |
| WebInspector.RemoteObject.prototype = { | |
| get objectId() | |
| { | |
| return this._objectId; | |
| }, | |
| get type() | |
| { | |
| return this._type; | |
| }, | |
| get subtype() | |
| { | |
| return this._subtype; | |
| }, | |
| get description() | |
| { | |
| return this._description; | |
| }, | |
| get hasChildren() | |
| { | |
| return this._hasChildren; | |
| }, | |
| get preview() | |
| { | |
| return this._preview; | |
| }, | |
| getOwnProperties: function(callback) | |
| { | |
| this._getProperties(true, callback); | |
| }, | |
| getAllProperties: function(callback) | |
| { | |
| this._getProperties(false, callback); | |
| }, | |
| _getProperties: function(ownProperties, callback) | |
| { | |
| if (!this._objectId) { | |
| callback([]); | |
| return; | |
| } | |
| function remoteObjectBinder(error, properties) | |
| { | |
| if (error) { | |
| callback(null); | |
| return; | |
| } | |
| var result = []; | |
| for (var i = 0; properties && i < properties.length; ++i) { | |
| var property = properties[i]; | |
| if (property.get || property.set) { | |
| if (property.get) | |
| result.push(new WebInspector.RemoteObjectProperty("get " + property.name, WebInspector.RemoteObject.fromPayload(property.get), property)); | |
| if (property.set) | |
| result.push(new WebInspector.RemoteObjectProperty("set " + property.name, WebInspector.RemoteObject.fromPayload(property.set), property)); | |
| } else | |
| result.push(new WebInspector.RemoteObjectProperty(property.name, WebInspector.RemoteObject.fromPayload(property.value), property)); | |
| } | |
| callback(result); | |
| } | |
| RuntimeAgent.getProperties(this._objectId, ownProperties, remoteObjectBinder); | |
| }, | |
| setPropertyValue: function(name, value, callback) | |
| { | |
| if (!this._objectId) { | |
| callback("Can't set a property of non-object."); | |
| return; | |
| } | |
| RuntimeAgent.evaluate.invoke({expression:value, doNotPauseOnExceptionsAndMuteConsole:true}, evaluatedCallback.bind(this)); | |
| function evaluatedCallback(error, result, wasThrown) | |
| { | |
| if (error || wasThrown) { | |
| callback(error || result.description); | |
| return; | |
| } | |
| function setPropertyValue(propertyName, propertyValue) | |
| { | |
| this[propertyName] = propertyValue; | |
| } | |
| delete result.description; | |
| RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], true, undefined, propertySetCallback.bind(this)); | |
| if (result._objectId) | |
| RuntimeAgent.releaseObject(result._objectId); | |
| } | |
| function propertySetCallback(error, result, wasThrown) | |
| { | |
| if (error || wasThrown) { | |
| callback(error || result.description); | |
| return; | |
| } | |
| callback(); | |
| } | |
| }, | |
| pushNodeToFrontend: function(callback) | |
| { | |
| if (this._objectId) | |
| WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback); | |
| else | |
| callback(0); | |
| }, | |
| callFunction: function(functionDeclaration, args, callback) | |
| { | |
| function mycallback(error, result, wasThrown) | |
| { | |
| if (!callback) | |
| return; | |
| callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result)); | |
| } | |
| RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, undefined, mycallback); | |
| }, | |
| callFunctionJSON: function(functionDeclaration, args, callback) | |
| { | |
| function mycallback(error, result, wasThrown) | |
| { | |
| callback((error || wasThrown) ? null : result.value); | |
| } | |
| RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, true, mycallback); | |
| }, | |
| release: function() | |
| { | |
| RuntimeAgent.releaseObject(this._objectId); | |
| }, | |
| arrayLength: function() | |
| { | |
| if (this.subtype !== "array") | |
| return 0; | |
| var matches = this._description.match(/\[([0-9]+)\]/); | |
| if (!matches) | |
| return 0; | |
| return parseInt(matches[1], 10); | |
| } | |
| } | |
| WebInspector.RemoteObjectProperty = function(name, value, descriptor) | |
| { | |
| this.name = name; | |
| this.value = value; | |
| this.enumerable = descriptor ? !!descriptor.enumerable : true; | |
| this.writable = descriptor ? !!descriptor.writable : true; | |
| if (descriptor && descriptor.wasThrown) | |
| this.wasThrown = true; | |
| } | |
| WebInspector.RemoteObjectProperty.fromPrimitiveValue = function(name, value) | |
| { | |
| return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value)); | |
| } | |
| WebInspector.RemoteObjectProperty.fromScopeValue = function(name, value) | |
| { | |
| var result = new WebInspector.RemoteObjectProperty(name, value); | |
| result.writable = false; | |
| return result; | |
| } | |
| WebInspector.LocalJSONObject = function(value) | |
| { | |
| this._value = value; | |
| } | |
| WebInspector.LocalJSONObject.prototype = { | |
| get description() | |
| { | |
| if (this._cachedDescription) | |
| return this._cachedDescription; | |
| if (this.type === "object") { | |
| switch (this.subtype) { | |
| case "array": | |
| function formatArrayItem(property) | |
| { | |
| return property.value.description; | |
| } | |
| this._cachedDescription = this._concatenate("[", "]", formatArrayItem); | |
| break; | |
| case "date": | |
| this._cachedDescription = "" + this._value; | |
| break; | |
| case "null": | |
| this._cachedDescription = "null"; | |
| break; | |
| default: | |
| function formatObjectItem(property) | |
| { | |
| return property.name + ":" + property.value.description; | |
| } | |
| this._cachedDescription = this._concatenate("{", "}", formatObjectItem); | |
| } | |
| } else | |
| this._cachedDescription = String(this._value); | |
| return this._cachedDescription; | |
| }, | |
| _concatenate: function(prefix, suffix, formatProperty) | |
| { | |
| const previewChars = 100; | |
| var buffer = prefix; | |
| var children = this._children(); | |
| for (var i = 0; i < children.length; ++i) { | |
| var itemDescription = formatProperty(children[i]); | |
| if (buffer.length + itemDescription.length > previewChars) { | |
| buffer += ",\u2026"; | |
| break; | |
| } | |
| if (i) | |
| buffer += ", "; | |
| buffer += itemDescription; | |
| } | |
| buffer += suffix; | |
| return buffer; | |
| }, | |
| get type() | |
| { | |
| return typeof this._value; | |
| }, | |
| get subtype() | |
| { | |
| if (this._value === null) | |
| return "null"; | |
| if (this._value instanceof Array) | |
| return "array"; | |
| if (this._value instanceof Date) | |
| return "date"; | |
| return undefined; | |
| }, | |
| get hasChildren() | |
| { | |
| return typeof this._value === "object" && this._value !== null && !!Object.keys(this._value).length; | |
| }, | |
| getOwnProperties: function(callback) | |
| { | |
| callback(this._children()); | |
| }, | |
| getAllProperties: function(callback) | |
| { | |
| callback(this._children()); | |
| }, | |
| _children: function() | |
| { | |
| if (!this.hasChildren) | |
| return []; | |
| function buildProperty(propName) | |
| { | |
| return new WebInspector.RemoteObjectProperty(propName, new WebInspector.LocalJSONObject(this._value[propName])); | |
| } | |
| if (!this._cachedChildren) | |
| this._cachedChildren = Object.keys(this._value || {}).map(buildProperty.bind(this)); | |
| return this._cachedChildren; | |
| }, | |
| isError: function() | |
| { | |
| return false; | |
| }, | |
| arrayLength: function() | |
| { | |
| return this._value instanceof Array ? this._value.length : 0; | |
| } | |
| } | |
| WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor) | |
| { | |
| this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties")); | |
| this.object = object; | |
| this.ignoreHasOwnProperty = ignoreHasOwnProperty; | |
| this.extraProperties = extraProperties; | |
| this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement; | |
| this.editable = true; | |
| this.skipProto = false; | |
| WebInspector.PropertiesSection.call(this, title || "", subtitle); | |
| } | |
| WebInspector.ObjectPropertiesSection._arrayLoadThreshold = 100; | |
| WebInspector.ObjectPropertiesSection.prototype = { | |
| enableContextMenu: function() | |
| { | |
| this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); | |
| }, | |
| _contextMenuEventFired: function(event) | |
| { | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| contextMenu.appendApplicableItems(this.object); | |
| contextMenu.show(event); | |
| }, | |
| onpopulate: function() | |
| { | |
| this.update(); | |
| }, | |
| update: function() | |
| { | |
| if (this.object.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) { | |
| this.propertiesTreeOutline.removeChildren(); | |
| WebInspector.ArrayGroupingTreeElement._populateArray(this.propertiesTreeOutline, this.object, 0, this.object.arrayLength() - 1); | |
| return; | |
| } | |
| function callback(properties) | |
| { | |
| if (!properties) | |
| return; | |
| this.updateProperties(properties); | |
| } | |
| if (this.ignoreHasOwnProperty) | |
| this.object.getAllProperties(callback.bind(this)); | |
| else | |
| this.object.getOwnProperties(callback.bind(this)); | |
| }, | |
| updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer) | |
| { | |
| if (!rootTreeElementConstructor) | |
| rootTreeElementConstructor = this.treeElementConstructor; | |
| if (!rootPropertyComparer) | |
| rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties; | |
| if (this.extraProperties) | |
| for (var i = 0; i < this.extraProperties.length; ++i) | |
| properties.push(this.extraProperties[i]); | |
| properties.sort(rootPropertyComparer); | |
| this.propertiesTreeOutline.removeChildren(); | |
| for (var i = 0; i < properties.length; ++i) { | |
| if (this.skipProto && properties[i].name === "__proto__") | |
| continue; | |
| properties[i].parentObject = this.object; | |
| } | |
| this.propertiesForTest = properties; | |
| for (var i = 0; i < properties.length; ++i) | |
| this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i])); | |
| if (!this.propertiesTreeOutline.children.length) { | |
| var title = document.createElement("div"); | |
| title.className = "info"; | |
| title.textContent = this.emptyPlaceholder; | |
| var infoElement = new TreeElement(title, null, false); | |
| this.propertiesTreeOutline.appendChild(infoElement); | |
| } | |
| } | |
| } | |
| WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; | |
| WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) | |
| { | |
| var a = propertyA.name; | |
| var b = propertyB.name; | |
| if (a === "__proto__") | |
| return 1; | |
| if (b === "__proto__") | |
| return -1; | |
| var diff = 0; | |
| var chunk = /^\d+|^\D+/; | |
| var chunka, chunkb, anum, bnum; | |
| while (diff === 0) { | |
| if (!a && b) | |
| return -1; | |
| if (!b && a) | |
| return 1; | |
| chunka = a.match(chunk)[0]; | |
| chunkb = b.match(chunk)[0]; | |
| anum = !isNaN(chunka); | |
| bnum = !isNaN(chunkb); | |
| if (anum && !bnum) | |
| return -1; | |
| if (bnum && !anum) | |
| return 1; | |
| if (anum && bnum) { | |
| diff = chunka - chunkb; | |
| if (diff === 0 && chunka.length !== chunkb.length) { | |
| if (!+chunka && !+chunkb) | |
| return chunka.length - chunkb.length; | |
| else | |
| return chunkb.length - chunka.length; | |
| } | |
| } else if (chunka !== chunkb) | |
| return (chunka < chunkb) ? -1 : 1; | |
| a = a.substring(chunka.length); | |
| b = b.substring(chunkb.length); | |
| } | |
| return diff; | |
| } | |
| WebInspector.ObjectPropertyTreeElement = function(property) | |
| { | |
| this.property = property; | |
| TreeElement.call(this, "", null, false); | |
| this.toggleOnClick = true; | |
| this.selectable = false; | |
| } | |
| WebInspector.ObjectPropertyTreeElement.prototype = { | |
| onpopulate: function() | |
| { | |
| return WebInspector.ObjectPropertyTreeElement.populate(this, this.property.value); | |
| }, | |
| ondblclick: function(event) | |
| { | |
| if (this.property.writable) | |
| this.startEditing(event); | |
| }, | |
| onattach: function() | |
| { | |
| this.update(); | |
| }, | |
| update: function() | |
| { | |
| this.nameElement = document.createElement("span"); | |
| this.nameElement.className = "name"; | |
| this.nameElement.textContent = this.property.name; | |
| if (!this.property.enumerable) | |
| this.nameElement.addStyleClass("dimmed"); | |
| var separatorElement = document.createElement("span"); | |
| separatorElement.className = "separator"; | |
| separatorElement.textContent = ": "; | |
| this.valueElement = document.createElement("span"); | |
| this.valueElement.className = "value"; | |
| var description = this.property.value.description; | |
| if (this.property.wasThrown) | |
| this.valueElement.textContent = "[Exception: " + description + "]"; | |
| else if (this.property.value.type === "string" && typeof description === "string") { | |
| this.valueElement.textContent = "\"" + description.replace(/\n/g, "\u21B5") + "\""; | |
| this.valueElement._originalTextContent = "\"" + description + "\""; | |
| } else if (this.property.value.type === "function" && typeof description === "string") { | |
| this.valueElement.textContent = /.*/.exec(description)[0].replace(/ +$/g, ""); | |
| this.valueElement._originalTextContent = description; | |
| } else | |
| this.valueElement.textContent = description; | |
| if (this.property.wasThrown) | |
| this.valueElement.addStyleClass("error"); | |
| if (this.property.value.subtype) | |
| this.valueElement.addStyleClass("console-formatted-" + this.property.value.subtype); | |
| else if (this.property.value.type) | |
| this.valueElement.addStyleClass("console-formatted-" + this.property.value.type); | |
| this.valueElement.addEventListener("contextmenu", this._contextMenuFired.bind(this, this.property.value), false); | |
| this.valueElement.title = description || ""; | |
| this.listItemElement.removeChildren(); | |
| this.listItemElement.appendChild(this.nameElement); | |
| this.listItemElement.appendChild(separatorElement); | |
| this.listItemElement.appendChild(this.valueElement); | |
| this.hasChildren = this.property.value.hasChildren && !this.property.wasThrown; | |
| }, | |
| _contextMenuFired: function(value, event) | |
| { | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| contextMenu.appendApplicableItems(value); | |
| contextMenu.show(event); | |
| }, | |
| updateSiblings: function() | |
| { | |
| if (this.parent.root) | |
| this.treeOutline.section.update(); | |
| else | |
| this.parent.shouldRefreshChildren = true; | |
| }, | |
| renderPromptAsBlock: function() | |
| { | |
| return false; | |
| }, | |
| elementAndValueToEdit: function(event) | |
| { | |
| return [this.valueElement, (typeof this.valueElement._originalTextContent === "string") ? this.valueElement._originalTextContent : undefined]; | |
| }, | |
| startEditing: function(event) | |
| { | |
| var elementAndValueToEdit = this.elementAndValueToEdit(event); | |
| var elementToEdit = elementAndValueToEdit[0]; | |
| var valueToEdit = elementAndValueToEdit[1]; | |
| if (WebInspector.isBeingEdited(elementToEdit) || !this.treeOutline.section.editable || this._readOnly) | |
| return; | |
| if (typeof valueToEdit !== "undefined") | |
| elementToEdit.textContent = valueToEdit; | |
| var context = { expanded: this.expanded, elementToEdit: elementToEdit, previousContent: elementToEdit.textContent }; | |
| this.hasChildren = false; | |
| this.listItemElement.addStyleClass("editing-sub-part"); | |
| this._prompt = new WebInspector.ObjectPropertyPrompt(this.editingCommitted.bind(this, null, elementToEdit.textContent, context.previousContent, context), this.editingCancelled.bind(this, null, context), this.renderPromptAsBlock()); | |
| function blurListener() | |
| { | |
| this.editingCommitted(null, elementToEdit.textContent, context.previousContent, context); | |
| } | |
| var proxyElement = this._prompt.attachAndStartEditing(elementToEdit, blurListener.bind(this)); | |
| window.getSelection().setBaseAndExtent(elementToEdit, 0, elementToEdit, 1); | |
| proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this, context), false); | |
| }, | |
| editingEnded: function(context) | |
| { | |
| this._prompt.detach(); | |
| delete this._prompt; | |
| this.listItemElement.scrollLeft = 0; | |
| this.listItemElement.removeStyleClass("editing-sub-part"); | |
| if (context.expanded) | |
| this.expand(); | |
| }, | |
| editingCancelled: function(element, context) | |
| { | |
| this.editingEnded(context); | |
| this.update(); | |
| }, | |
| editingCommitted: function(element, userInput, previousContent, context) | |
| { | |
| if (userInput === previousContent) | |
| return this.editingCancelled(element, context); | |
| this.editingEnded(context); | |
| this.applyExpression(userInput, true); | |
| }, | |
| _promptKeyDown: function(context, event) | |
| { | |
| if (isEnterKey(event)) { | |
| event.consume(true); | |
| return this.editingCommitted(null, context.elementToEdit.textContent, context.previousContent, context); | |
| } | |
| if (event.keyIdentifier === "U+001B") { | |
| event.consume(); | |
| return this.editingCancelled(null, context); | |
| } | |
| }, | |
| applyExpression: function(expression, updateInterface) | |
| { | |
| expression = expression.trim(); | |
| var expressionLength = expression.length; | |
| function callback(error) | |
| { | |
| if (!updateInterface) | |
| return; | |
| if (error) | |
| this.update(); | |
| if (!expressionLength) { | |
| this.parent.removeChild(this); | |
| } else { | |
| this.updateSiblings(); | |
| } | |
| }; | |
| this.property.parentObject.setPropertyValue(this.property.name, expression.trim(), callback.bind(this)); | |
| } | |
| } | |
| WebInspector.ObjectPropertyTreeElement.populate = function(treeElement, value) { | |
| if (treeElement.children.length && !treeElement.shouldRefreshChildren) | |
| return; | |
| if (value.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) { | |
| treeElement.removeChildren(); | |
| WebInspector.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1); | |
| return; | |
| } | |
| function callback(properties) | |
| { | |
| treeElement.removeChildren(); | |
| if (!properties) | |
| return; | |
| properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); | |
| for (var i = 0; i < properties.length; ++i) { | |
| if (treeElement.treeOutline.section.skipProto && properties[i].name === "__proto__") | |
| continue; | |
| properties[i].parentObject = value; | |
| treeElement.appendChild(new treeElement.treeOutline.section.treeElementConstructor(properties[i])); | |
| } | |
| if (value.type === "function") | |
| treeElement.appendChild(new WebInspector.FunctionScopeMainTreeElement(value)); | |
| } | |
| value.getOwnProperties(callback); | |
| } | |
| WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.FunctionScopeMainTreeElement = function(remoteObject) | |
| { | |
| TreeElement.call(this, "<function scope>", null, false); | |
| this.toggleOnClick = true; | |
| this.selectable = false; | |
| this._remoteObject = remoteObject; | |
| this.hasChildren = true; | |
| } | |
| WebInspector.FunctionScopeMainTreeElement.prototype = { | |
| onpopulate: function() | |
| { | |
| if (this.children.length && !this.shouldRefreshChildren) | |
| return; | |
| function didGetDetails(error, response) | |
| { | |
| if (error) { | |
| console.error(error); | |
| return; | |
| } | |
| this.removeChildren(); | |
| var scopeChain = response.scopeChain; | |
| for (var i = 0; i < scopeChain.length; ++i) { | |
| var scope = scopeChain[i]; | |
| var title = null; | |
| var isTrueObject; | |
| switch (scope.type) { | |
| case "local": | |
| title = WebInspector.UIString("Local"); | |
| isTrueObject = false; | |
| break; | |
| case "closure": | |
| title = WebInspector.UIString("Closure"); | |
| isTrueObject = false; | |
| break; | |
| case "catch": | |
| title = WebInspector.UIString("Catch"); | |
| isTrueObject = false; | |
| break; | |
| case "with": | |
| title = WebInspector.UIString("With Block"); | |
| isTrueObject = true; | |
| break; | |
| case "global": | |
| title = WebInspector.UIString("Global"); | |
| isTrueObject = true; | |
| break; | |
| } | |
| var remoteObject = WebInspector.RemoteObject.fromPayload(scope.object); | |
| if (isTrueObject) { | |
| var property = WebInspector.RemoteObjectProperty.fromScopeValue(title, remoteObject); | |
| property.parentObject = null; | |
| this.appendChild(new this.treeOutline.section.treeElementConstructor(property)); | |
| } else { | |
| var scopeTreeElement = new WebInspector.ScopeTreeElement(title, null, remoteObject); | |
| this.appendChild(scopeTreeElement); | |
| } | |
| } | |
| } | |
| DebuggerAgent.getFunctionDetails(this._remoteObject.objectId, didGetDetails.bind(this)); | |
| } | |
| }; | |
| WebInspector.FunctionScopeMainTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.ScopeTreeElement = function(title, subtitle, remoteObject) | |
| { | |
| TreeElement.call(this, title, null, false); | |
| this.toggleOnClick = true; | |
| this.selectable = false; | |
| this._remoteObject = remoteObject; | |
| this.hasChildren = true; | |
| } | |
| WebInspector.ScopeTreeElement.prototype = { | |
| onpopulate: function() | |
| { | |
| return WebInspector.ObjectPropertyTreeElement.populate(this, this._remoteObject); | |
| } | |
| }; | |
| WebInspector.ScopeTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.ArrayGroupingTreeElement = function(object, fromIndex, toIndex, propertyCount) | |
| { | |
| TreeElement.call(this, String.sprintf("[%d \u2026 %d]", fromIndex, toIndex), undefined, true); | |
| this._fromIndex = fromIndex; | |
| this._toIndex = toIndex; | |
| this._object = object; | |
| this._readOnly = true; | |
| this._propertyCount = propertyCount; | |
| this._populated = false; | |
| } | |
| WebInspector.ArrayGroupingTreeElement._bucketThreshold = 100; | |
| WebInspector.ArrayGroupingTreeElement._populateArray = function(treeElement, object, fromIndex, toIndex) | |
| { | |
| WebInspector.ArrayGroupingTreeElement._populateRanges(treeElement, object, fromIndex, toIndex, true); | |
| } | |
| WebInspector.ArrayGroupingTreeElement._populateRanges = function(treeElement, object, fromIndex, toIndex, topLevel) | |
| { | |
| object.callFunctionJSON(packRanges, [{value: fromIndex}, {value: toIndex}, {value: WebInspector.ArrayGroupingTreeElement._bucketThreshold}], callback.bind(this)); | |
| function packRanges(fromIndex, toIndex, bucketThreshold) | |
| { | |
| var count = 0; | |
| for (var i = fromIndex; i <= toIndex; ++i) { | |
| var value = this[i]; | |
| if (typeof value !== "undefined") | |
| ++count; | |
| } | |
| var bucketSize = count; | |
| if (count <= bucketThreshold) | |
| bucketSize = count; | |
| else | |
| bucketSize = Math.pow(bucketThreshold, Math.floor(Math.log(count) / Math.log(bucketThreshold))); | |
| var ranges = []; | |
| count = 0; | |
| var groupStart = -1; | |
| var groupEnd = 0; | |
| for (var i = fromIndex; i <= toIndex; ++i) { | |
| var value = this[i]; | |
| if (typeof value === "undefined") | |
| continue; | |
| if (groupStart === -1) | |
| groupStart = i; | |
| groupEnd = i; | |
| if (++count === bucketSize) { | |
| ranges.push([groupStart, groupEnd, count]); | |
| count = 0; | |
| groupStart = -1; | |
| } | |
| } | |
| if (count > 0) | |
| ranges.push([groupStart, groupEnd, count]); | |
| return ranges; | |
| } | |
| function callback(ranges) | |
| { | |
| if (ranges.length == 1) | |
| WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeElement, object, ranges[0][0], ranges[0][1]); | |
| else { | |
| for (var i = 0; i < ranges.length; ++i) { | |
| var fromIndex = ranges[i][0]; | |
| var toIndex = ranges[i][1]; | |
| var count = ranges[i][2]; | |
| if (fromIndex == toIndex) | |
| WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeElement, object, fromIndex, toIndex); | |
| else | |
| treeElement.appendChild(new WebInspector.ArrayGroupingTreeElement(object, fromIndex, toIndex, count)); | |
| } | |
| } | |
| if (topLevel) | |
| WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties(treeElement, object); | |
| } | |
| } | |
| WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeElement, object, fromIndex, toIndex) | |
| { | |
| object.callFunction(buildArrayFragment, [{value: fromIndex}, {value: toIndex}], processArrayFragment.bind(this)); | |
| function buildArrayFragment(fromIndex, toIndex) | |
| { | |
| var result = Object.create(null); | |
| for (var i = fromIndex; i <= toIndex; ++i) { | |
| var value = this[i]; | |
| if (typeof value !== "undefined") | |
| result[i] = value; | |
| } | |
| return result; | |
| } | |
| function processArrayFragment(arrayFragment) | |
| { | |
| arrayFragment.getAllProperties(processProperties.bind(this)); | |
| } | |
| function processProperties(properties) | |
| { | |
| if (!properties) | |
| return; | |
| properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); | |
| for (var i = 0; i < properties.length; ++i) { | |
| properties[i].parentObject = this._object; | |
| var childTreeElement = new treeElement.treeOutline.section.treeElementConstructor(properties[i]); | |
| childTreeElement._readOnly = true; | |
| treeElement.appendChild(childTreeElement); | |
| } | |
| } | |
| } | |
| WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(treeElement, object) | |
| { | |
| object.callFunction(buildObjectFragment, undefined, processObjectFragment.bind(this)); | |
| function buildObjectFragment() | |
| { | |
| var result = Object.create(this.__proto__); | |
| var names = Object.getOwnPropertyNames(this); | |
| for (var i = 0; i < names.length; ++i) { | |
| var name = names[i]; | |
| if (!isNaN(name)) | |
| continue; | |
| var descriptor = Object.getOwnPropertyDescriptor(this, name); | |
| if (descriptor) | |
| Object.defineProperty(result, name, descriptor); | |
| } | |
| return result; | |
| } | |
| function processObjectFragment(arrayFragment) | |
| { | |
| arrayFragment.getOwnProperties(processProperties.bind(this)); | |
| } | |
| function processProperties(properties) | |
| { | |
| if (!properties) | |
| return; | |
| properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); | |
| for (var i = 0; i < properties.length; ++i) { | |
| properties[i].parentObject = this._object; | |
| var childTreeElement = new treeElement.treeOutline.section.treeElementConstructor(properties[i]); | |
| childTreeElement._readOnly = true; | |
| treeElement.appendChild(childTreeElement); | |
| } | |
| } | |
| } | |
| WebInspector.ArrayGroupingTreeElement.prototype = { | |
| onpopulate: function() | |
| { | |
| if (this._populated) | |
| return; | |
| this._populated = true; | |
| if (this._propertyCount >= WebInspector.ArrayGroupingTreeElement._bucketThreshold) { | |
| WebInspector.ArrayGroupingTreeElement._populateRanges(this, this._object, this._fromIndex, this._toIndex, false); | |
| return; | |
| } | |
| WebInspector.ArrayGroupingTreeElement._populateAsFragment(this, this._object, this._fromIndex, this._toIndex); | |
| }, | |
| onattach: function() | |
| { | |
| this.listItemElement.addStyleClass("name"); | |
| } | |
| } | |
| WebInspector.ArrayGroupingTreeElement.prototype.__proto__ = TreeElement.prototype; | |
| WebInspector.ObjectPropertyPrompt = function(commitHandler, cancelHandler, renderAsBlock) | |
| { | |
| const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>."; | |
| WebInspector.TextPrompt.call(this, WebInspector.consoleView.completionsForTextPrompt.bind(WebInspector.consoleView), ExpressionStopCharacters); | |
| this.setSuggestBoxEnabled("generic-suggest"); | |
| if (renderAsBlock) | |
| this.renderAsBlock(); | |
| } | |
| WebInspector.ObjectPropertyPrompt.prototype.__proto__ = WebInspector.TextPrompt.prototype; | |
| WebInspector.ObjectPopoverHelper = function(panelElement, getAnchor, queryObject, onHide, disableOnClick) | |
| { | |
| WebInspector.PopoverHelper.call(this, panelElement, getAnchor, this._showObjectPopover.bind(this), this._onHideObjectPopover.bind(this), disableOnClick); | |
| this._queryObject = queryObject; | |
| this._onHideCallback = onHide; | |
| this._popoverObjectGroup = "popover"; | |
| panelElement.addEventListener("scroll", this.hidePopover.bind(this), true); | |
| }; | |
| WebInspector.ObjectPopoverHelper.prototype = { | |
| _showObjectPopover: function(element, popover) | |
| { | |
| function showObjectPopover(result, wasThrown, anchorOverride) | |
| { | |
| if (popover.disposed) | |
| return; | |
| if (wasThrown) { | |
| this.hidePopover(); | |
| return; | |
| } | |
| var anchorElement = anchorOverride || element; | |
| var popoverContentElement = null; | |
| if (result.type !== "object") { | |
| popoverContentElement = document.createElement("span"); | |
| popoverContentElement.className = "monospace console-formatted-" + result.type; | |
| popoverContentElement.style.whiteSpace = "pre"; | |
| popoverContentElement.textContent = result.description; | |
| if (result.type === "function") { | |
| function didGetDetails(error, response) | |
| { | |
| if (error) { | |
| console.error(error); | |
| return; | |
| } | |
| var container = document.createElement("div"); | |
| container.style.display = "inline-block"; | |
| var title = container.createChild("div", "function-popover-title source-code"); | |
| var functionName = title.createChild("span", "function-name"); | |
| functionName.textContent = response.name || response.inferredName || response.displayName || WebInspector.UIString("(anonymous function)"); | |
| this._linkifier = new WebInspector.Linkifier(); | |
| var rawLocation = response.location; | |
| var link = this._linkifier.linkifyRawLocation(rawLocation, "function-location-link"); | |
| if (link) | |
| title.appendChild(link); | |
| container.appendChild(popoverContentElement); | |
| popover.show(container, anchorElement); | |
| } | |
| DebuggerAgent.getFunctionDetails(result.objectId, didGetDetails.bind(this)); | |
| return; | |
| } | |
| if (result.type === "string") | |
| popoverContentElement.textContent = "\"" + popoverContentElement.textContent + "\""; | |
| popover.show(popoverContentElement, anchorElement); | |
| } else { | |
| popoverContentElement = document.createElement("div"); | |
| this._titleElement = document.createElement("div"); | |
| this._titleElement.className = "source-frame-popover-title monospace"; | |
| this._titleElement.textContent = result.description; | |
| popoverContentElement.appendChild(this._titleElement); | |
| var section = new WebInspector.ObjectPropertiesSection(result); | |
| if (result.description.substr(0, 4) === "HTML") { | |
| this._sectionUpdateProperties = section.updateProperties.bind(section); | |
| section.updateProperties = this._updateHTMLId.bind(this); | |
| } | |
| section.expanded = true; | |
| section.element.addStyleClass("source-frame-popover-tree"); | |
| section.headerElement.addStyleClass("hidden"); | |
| popoverContentElement.appendChild(section.element); | |
| const popoverWidth = 300; | |
| const popoverHeight = 250; | |
| popover.show(popoverContentElement, anchorElement, popoverWidth, popoverHeight); | |
| } | |
| } | |
| this._queryObject(element, showObjectPopover.bind(this), this._popoverObjectGroup); | |
| }, | |
| _onHideObjectPopover: function() | |
| { | |
| if (this._linkifier) { | |
| this._linkifier.reset(); | |
| delete this._linkifier; | |
| } | |
| if (this._onHideCallback) | |
| this._onHideCallback(); | |
| RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup); | |
| }, | |
| _updateHTMLId: function(properties, rootTreeElementConstructor, rootPropertyComparer) | |
| { | |
| for (var i = 0; i < properties.length; ++i) { | |
| if (properties[i].name === "id") { | |
| if (properties[i].value.description) | |
| this._titleElement.textContent += "#" + properties[i].value.description; | |
| break; | |
| } | |
| } | |
| this._sectionUpdateProperties(properties, rootTreeElementConstructor, rootPropertyComparer); | |
| } | |
| } | |
| WebInspector.ObjectPopoverHelper.prototype.__proto__ = WebInspector.PopoverHelper.prototype; | |
| WebInspector.NativeBreakpointsSidebarPane = function(title) | |
| { | |
| WebInspector.SidebarPane.call(this, title); | |
| this.listElement = document.createElement("ol"); | |
| this.listElement.className = "breakpoint-list"; | |
| this.emptyElement = document.createElement("div"); | |
| this.emptyElement.className = "info"; | |
| this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); | |
| this.bodyElement.appendChild(this.emptyElement); | |
| } | |
| WebInspector.NativeBreakpointsSidebarPane.prototype = { | |
| _addListElement: function(element, beforeElement) | |
| { | |
| if (beforeElement) | |
| this.listElement.insertBefore(element, beforeElement); | |
| else { | |
| if (!this.listElement.firstChild) { | |
| this.bodyElement.removeChild(this.emptyElement); | |
| this.bodyElement.appendChild(this.listElement); | |
| } | |
| this.listElement.appendChild(element); | |
| } | |
| }, | |
| _removeListElement: function(element) | |
| { | |
| this.listElement.removeChild(element); | |
| if (!this.listElement.firstChild) { | |
| this.bodyElement.removeChild(this.listElement); | |
| this.bodyElement.appendChild(this.emptyElement); | |
| } | |
| }, | |
| _reset: function() | |
| { | |
| this.listElement.removeChildren(); | |
| if (this.listElement.parentElement) { | |
| this.bodyElement.removeChild(this.listElement); | |
| this.bodyElement.appendChild(this.emptyElement); | |
| } | |
| } | |
| } | |
| WebInspector.NativeBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; | |
| WebInspector.DOMBreakpointsSidebarPane = function() | |
| { | |
| WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("DOM Breakpoints")); | |
| this._breakpointElements = {}; | |
| this._breakpointTypes = { | |
| SubtreeModified: "subtree-modified", | |
| AttributeModified: "attribute-modified", | |
| NodeRemoved: "node-removed" | |
| }; | |
| this._breakpointTypeLabels = {}; | |
| this._breakpointTypeLabels[this._breakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified"); | |
| this._breakpointTypeLabels[this._breakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified"); | |
| this._breakpointTypeLabels[this._breakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed"); | |
| this._contextMenuLabels = {}; | |
| this._contextMenuLabels[this._breakpointTypes.SubtreeModified] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Subtree modifications" : "Subtree Modifications"); | |
| this._contextMenuLabels[this._breakpointTypes.AttributeModified] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Attributes modifications" : "Attributes Modifications"); | |
| this._contextMenuLabels[this._breakpointTypes.NodeRemoved] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Node removal" : "Node Removal"); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this); | |
| WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this); | |
| } | |
| WebInspector.DOMBreakpointsSidebarPane.prototype = { | |
| _inspectedURLChanged: function(event) | |
| { | |
| this._breakpointElements = {}; | |
| this._reset(); | |
| var url = event.data; | |
| this._inspectedURL = url.removeURLFragment(); | |
| }, | |
| populateNodeContextMenu: function(node, contextMenu) | |
| { | |
| var nodeBreakpoints = {}; | |
| for (var id in this._breakpointElements) { | |
| var element = this._breakpointElements[id]; | |
| if (element._node === node) | |
| nodeBreakpoints[element._type] = true; | |
| } | |
| function toggleBreakpoint(type) | |
| { | |
| if (!nodeBreakpoints[type]) | |
| this._setBreakpoint(node, type, true); | |
| else | |
| this._removeBreakpoint(node, type); | |
| this._saveBreakpoints(); | |
| } | |
| var breakPointSubMenu = contextMenu.appendSubMenuItem(WebInspector.UIString("Break on...")); | |
| for (var key in this._breakpointTypes) { | |
| var type = this._breakpointTypes[key]; | |
| var label = this._contextMenuLabels[type]; | |
| breakPointSubMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints[type]); | |
| } | |
| }, | |
| createBreakpointHitStatusMessage: function(auxData, callback) | |
| { | |
| if (auxData.type === this._breakpointTypes.SubtreeModified) { | |
| var targetNodeObject = WebInspector.RemoteObject.fromPayload(auxData["targetNode"]); | |
| function didPushNodeToFrontend(targetNodeId) | |
| { | |
| if (targetNodeId) | |
| targetNodeObject.release(); | |
| this._doCreateBreakpointHitStatusMessage(auxData, targetNodeId, callback); | |
| } | |
| targetNodeObject.pushNodeToFrontend(didPushNodeToFrontend.bind(this)); | |
| } else | |
| this._doCreateBreakpointHitStatusMessage(auxData, null, callback); | |
| }, | |
| _doCreateBreakpointHitStatusMessage: function (auxData, targetNodeId, callback) | |
| { | |
| var message; | |
| var typeLabel = this._breakpointTypeLabels[auxData.type]; | |
| var linkifiedNode = WebInspector.DOMPresentationUtils.linkifyNodeById(auxData.nodeId); | |
| var substitutions = [typeLabel, linkifiedNode]; | |
| var targetNode = ""; | |
| if (targetNodeId) | |
| targetNode = WebInspector.DOMPresentationUtils.linkifyNodeById(targetNodeId); | |
| if (auxData.type === this._breakpointTypes.SubtreeModified) { | |
| if (auxData.insertion) { | |
| if (targetNodeId !== auxData.nodeId) { | |
| message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s."; | |
| substitutions.push(targetNode); | |
| } else | |
| message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node."; | |
| } else { | |
| message = "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed."; | |
| substitutions.push(targetNode); | |
| } | |
| } else | |
| message = "Paused on a \"%s\" breakpoint set on %s."; | |
| var element = document.createElement("span"); | |
| var formatters = { | |
| s: function(substitution) | |
| { | |
| return substitution; | |
| } | |
| }; | |
| function append(a, b) | |
| { | |
| if (typeof b === "string") | |
| b = document.createTextNode(b); | |
| element.appendChild(b); | |
| } | |
| WebInspector.formatLocalized(message, substitutions, formatters, "", append); | |
| callback(element); | |
| }, | |
| _nodeRemoved: function(event) | |
| { | |
| var node = event.data.node; | |
| this._removeBreakpointsForNode(event.data.node); | |
| if (!node.children) | |
| return; | |
| for (var i = 0; i < node.children.length; ++i) | |
| this._removeBreakpointsForNode(node.children[i]); | |
| this._saveBreakpoints(); | |
| }, | |
| _removeBreakpointsForNode: function(node) | |
| { | |
| for (var id in this._breakpointElements) { | |
| var element = this._breakpointElements[id]; | |
| if (element._node === node) | |
| this._removeBreakpoint(element._node, element._type); | |
| } | |
| }, | |
| _setBreakpoint: function(node, type, enabled) | |
| { | |
| var breakpointId = this._createBreakpointId(node.id, type); | |
| if (breakpointId in this._breakpointElements) | |
| return; | |
| var element = document.createElement("li"); | |
| element._node = node; | |
| element._type = type; | |
| element.addEventListener("contextmenu", this._contextMenu.bind(this, node, type), true); | |
| var checkboxElement = document.createElement("input"); | |
| checkboxElement.className = "checkbox-elem"; | |
| checkboxElement.type = "checkbox"; | |
| checkboxElement.checked = enabled; | |
| checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, node, type), false); | |
| element._checkboxElement = checkboxElement; | |
| element.appendChild(checkboxElement); | |
| var labelElement = document.createElement("span"); | |
| element.appendChild(labelElement); | |
| var linkifiedNode = WebInspector.DOMPresentationUtils.linkifyNodeById(node.id); | |
| linkifiedNode.addStyleClass("monospace"); | |
| labelElement.appendChild(linkifiedNode); | |
| var description = document.createElement("div"); | |
| description.className = "source-text"; | |
| description.textContent = this._breakpointTypeLabels[type]; | |
| labelElement.appendChild(description); | |
| var currentElement = this.listElement.firstChild; | |
| while (currentElement) { | |
| if (currentElement._type && currentElement._type < element._type) | |
| break; | |
| currentElement = currentElement.nextSibling; | |
| } | |
| this._addListElement(element, currentElement); | |
| this._breakpointElements[breakpointId] = element; | |
| if (enabled) | |
| DOMDebuggerAgent.setDOMBreakpoint(node.id, type); | |
| }, | |
| _removeAllBreakpoints: function() | |
| { | |
| for (var id in this._breakpointElements) { | |
| var element = this._breakpointElements[id]; | |
| this._removeBreakpoint(element._node, element._type); | |
| } | |
| this._saveBreakpoints(); | |
| }, | |
| _removeBreakpoint: function(node, type) | |
| { | |
| var breakpointId = this._createBreakpointId(node.id, type); | |
| var element = this._breakpointElements[breakpointId]; | |
| if (!element) | |
| return; | |
| this._removeListElement(element); | |
| delete this._breakpointElements[breakpointId]; | |
| if (element._checkboxElement.checked) | |
| DOMDebuggerAgent.removeDOMBreakpoint(node.id, type); | |
| }, | |
| _contextMenu: function(node, type, event) | |
| { | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| function removeBreakpoint() | |
| { | |
| this._removeBreakpoint(node, type); | |
| this._saveBreakpoints(); | |
| } | |
| contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all DOM breakpoints" : "Remove All DOM Breakpoints"), this._removeAllBreakpoints.bind(this)); | |
| contextMenu.show(event); | |
| }, | |
| _checkboxClicked: function(node, type, event) | |
| { | |
| if (event.target.checked) | |
| DOMDebuggerAgent.setDOMBreakpoint(node.id, type); | |
| else | |
| DOMDebuggerAgent.removeDOMBreakpoint(node.id, type); | |
| this._saveBreakpoints(); | |
| }, | |
| highlightBreakpoint: function(auxData) | |
| { | |
| var breakpointId = this._createBreakpointId(auxData.nodeId, auxData.type); | |
| var element = this._breakpointElements[breakpointId]; | |
| if (!element) | |
| return; | |
| this.expanded = true; | |
| element.addStyleClass("breakpoint-hit"); | |
| this._highlightedElement = element; | |
| }, | |
| clearBreakpointHighlight: function() | |
| { | |
| if (this._highlightedElement) { | |
| this._highlightedElement.removeStyleClass("breakpoint-hit"); | |
| delete this._highlightedElement; | |
| } | |
| }, | |
| _createBreakpointId: function(nodeId, type) | |
| { | |
| return nodeId + ":" + type; | |
| }, | |
| _saveBreakpoints: function() | |
| { | |
| var breakpoints = []; | |
| var storedBreakpoints = WebInspector.settings.domBreakpoints.get(); | |
| for (var i = 0; i < storedBreakpoints.length; ++i) { | |
| var breakpoint = storedBreakpoints[i]; | |
| if (breakpoint.url !== this._inspectedURL) | |
| breakpoints.push(breakpoint); | |
| } | |
| for (var id in this._breakpointElements) { | |
| var element = this._breakpointElements[id]; | |
| breakpoints.push({ url: this._inspectedURL, path: element._node.path(), type: element._type, enabled: element._checkboxElement.checked }); | |
| } | |
| WebInspector.settings.domBreakpoints.set(breakpoints); | |
| }, | |
| restoreBreakpoints: function() | |
| { | |
| var pathToBreakpoints = {}; | |
| function didPushNodeByPathToFrontend(path, nodeId) | |
| { | |
| var node = WebInspector.domAgent.nodeForId(nodeId); | |
| if (!node) | |
| return; | |
| var breakpoints = pathToBreakpoints[path]; | |
| for (var i = 0; i < breakpoints.length; ++i) | |
| this._setBreakpoint(node, breakpoints[i].type, breakpoints[i].enabled); | |
| } | |
| var breakpoints = WebInspector.settings.domBreakpoints.get(); | |
| for (var i = 0; i < breakpoints.length; ++i) { | |
| var breakpoint = breakpoints[i]; | |
| if (breakpoint.url !== this._inspectedURL) | |
| continue; | |
| var path = breakpoint.path; | |
| if (!pathToBreakpoints[path]) { | |
| pathToBreakpoints[path] = []; | |
| WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path)); | |
| } | |
| pathToBreakpoints[path].push(breakpoint); | |
| } | |
| } | |
| } | |
| WebInspector.DOMBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype; | |
| WebInspector.Color = function(str) | |
| { | |
| this.value = str; | |
| this._parse(); | |
| } | |
| WebInspector.Color.fromRGBA = function(r, g, b, a) | |
| { | |
| return new WebInspector.Color("rgba(" + r + "," + g + "," + b + "," + (typeof a === "undefined" ? 1 : a) + ")"); | |
| } | |
| WebInspector.Color.fromRGB = function(r, g, b) | |
| { | |
| return new WebInspector.Color("rgb(" + r + "," + g + "," + b + ")"); | |
| } | |
| WebInspector.Color.prototype = { | |
| get shorthex() | |
| { | |
| if ("_short" in this) | |
| return this._short; | |
| if (!this.simple) | |
| return ""; | |
| var hex = this.hex; | |
| if (hex.charAt(0) === hex.charAt(1) && hex.charAt(2) === hex.charAt(3) && hex.charAt(4) === hex.charAt(5)) | |
| this._short = hex.charAt(0) + hex.charAt(2) + hex.charAt(4); | |
| else | |
| this._short = hex; | |
| return this._short; | |
| }, | |
| get hex() | |
| { | |
| if (!this.simple) | |
| return ""; | |
| return this._hex; | |
| }, | |
| set hex(x) | |
| { | |
| this._hex = x; | |
| }, | |
| get rgb() | |
| { | |
| if (this._rgb) | |
| return this._rgb; | |
| if (this.simple) | |
| this._rgb = this._hexToRGB(this.hex); | |
| else { | |
| var rgba = this.rgba; | |
| this._rgb = [rgba[0], rgba[1], rgba[2]]; | |
| } | |
| return this._rgb; | |
| }, | |
| set rgb(x) | |
| { | |
| this._rgb = x; | |
| }, | |
| get hsl() | |
| { | |
| if (this._hsl) | |
| return this._hsl; | |
| this._hsl = this._rgbToHSL(this.rgb); | |
| return this._hsl; | |
| }, | |
| set hsl(x) | |
| { | |
| this._hsl = x; | |
| }, | |
| get nickname() | |
| { | |
| if (typeof this._nickname !== "undefined") | |
| return this._nickname; | |
| else | |
| return ""; | |
| }, | |
| set nickname(x) | |
| { | |
| this._nickname = x; | |
| }, | |
| get rgba() | |
| { | |
| return this._rgba; | |
| }, | |
| set rgba(x) | |
| { | |
| this._rgba = x; | |
| }, | |
| get hsla() | |
| { | |
| return this._hsla; | |
| }, | |
| set hsla(x) | |
| { | |
| this._hsla = x; | |
| }, | |
| hasShortHex: function() | |
| { | |
| var shorthex = this.shorthex; | |
| return (!!shorthex && shorthex.length === 3); | |
| }, | |
| toString: function(format) | |
| { | |
| if (!format) | |
| format = this.format; | |
| switch (format) { | |
| case "original": | |
| return this.value; | |
| case "rgb": | |
| return "rgb(" + this.rgb.join(", ") + ")"; | |
| case "rgba": | |
| return "rgba(" + this.rgba.join(", ") + ")"; | |
| case "hsl": | |
| var hsl = this.hsl; | |
| return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)"; | |
| case "hsla": | |
| var hsla = this.hsla; | |
| return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")"; | |
| case "hex": | |
| return "#" + this.hex; | |
| case "shorthex": | |
| return "#" + this.shorthex; | |
| case "nickname": | |
| return this.nickname; | |
| } | |
| throw "invalid color format"; | |
| }, | |
| toProtocolRGBA: function() | |
| { | |
| if (this._protocolRGBA) | |
| return this._protocolRGBA; | |
| var components = this.rgba; | |
| if (components) | |
| this._protocolRGBA = { r: Number(components[0]), g: Number(components[1]), b: Number(components[2]), a: Number(components[3]) }; | |
| else { | |
| components = this.rgb; | |
| this._protocolRGBA = { r: Number(components[0]), g: Number(components[1]), b: Number(components[2]) }; | |
| } | |
| return this._protocolRGBA; | |
| }, | |
| _clamp: function(value, min, max) | |
| { | |
| if (value < min) | |
| return min; | |
| if (value > max) | |
| return max; | |
| return value; | |
| }, | |
| _individualRGBValueToFloatValue: function(rgbValue) | |
| { | |
| if (typeof rgbValue === "number") | |
| return this._clamp(rgbValue, 0, 255); | |
| if (rgbValue.indexOf("%") === -1) { | |
| var intValue = parseInt(rgbValue, 10); | |
| return this._clamp(intValue, 0, 255); | |
| } | |
| var percentValue = parseFloat(rgbValue); | |
| return this._clamp(percentValue, 0, 100) * 2.55; | |
| }, | |
| _individualRGBValueToHexValue: function(rgbValue) | |
| { | |
| var floatValue = this._individualRGBValueToFloatValue(rgbValue); | |
| var hex = Math.round(floatValue).toString(16); | |
| if (hex.length === 1) | |
| hex = "0" + hex; | |
| return hex; | |
| }, | |
| _rgbStringsToHex: function(rgb) | |
| { | |
| var r = this._individualRGBValueToHexValue(rgb[0]); | |
| var g = this._individualRGBValueToHexValue(rgb[1]); | |
| var b = this._individualRGBValueToHexValue(rgb[2]); | |
| return (r + g + b).toUpperCase(); | |
| }, | |
| _rgbToHex: function(rgb) | |
| { | |
| var r = this._individualRGBValueToHexValue(rgb[0]); | |
| var g = this._individualRGBValueToHexValue(rgb[1]); | |
| var b = this._individualRGBValueToHexValue(rgb[2]); | |
| return (r + g + b).toUpperCase(); | |
| }, | |
| _hexToRGB: function(hex) | |
| { | |
| var r = parseInt(hex.substring(0,2), 16); | |
| var g = parseInt(hex.substring(2,4), 16); | |
| var b = parseInt(hex.substring(4,6), 16); | |
| return [r, g, b]; | |
| }, | |
| _rgbToHSL: function(rgb) | |
| { | |
| var r = this._individualRGBValueToFloatValue(rgb[0]) / 255; | |
| var g = this._individualRGBValueToFloatValue(rgb[1]) / 255; | |
| var b = this._individualRGBValueToFloatValue(rgb[2]) / 255; | |
| var max = Math.max(r, g, b); | |
| var min = Math.min(r, g, b); | |
| var diff = max - min; | |
| var add = max + min; | |
| if (min === max) | |
| var h = 0; | |
| else if (r === max) | |
| var h = ((60 * (g - b) / diff) + 360) % 360; | |
| else if (g === max) | |
| var h = (60 * (b - r) / diff) + 120; | |
| else | |
| var h = (60 * (r - g) / diff) + 240; | |
| var l = 0.5 * add; | |
| if (l === 0) | |
| var s = 0; | |
| else if (l === 1) | |
| var s = 1; | |
| else if (l <= 0.5) | |
| var s = diff / add; | |
| else | |
| var s = diff / (2 - add); | |
| h = Math.round(h); | |
| s = Math.round(s*100); | |
| l = Math.round(l*100); | |
| return [h, s, l]; | |
| }, | |
| _hslToRGB: function(hsl) | |
| { | |
| var h = parseFloat(hsl[0]) / 360; | |
| var s = parseFloat(hsl[1]) / 100; | |
| var l = parseFloat(hsl[2]) / 100; | |
| if (s < 0) | |
| s = 0; | |
| if (l <= 0.5) | |
| var q = l * (1 + s); | |
| else | |
| var q = l + s - (l * s); | |
| var p = 2 * l - q; | |
| var tr = h + (1 / 3); | |
| var tg = h; | |
| var tb = h - (1 / 3); | |
| var r = Math.round(hueToRGB(p, q, tr) * 255); | |
| var g = Math.round(hueToRGB(p, q, tg) * 255); | |
| var b = Math.round(hueToRGB(p, q, tb) * 255); | |
| return [r, g, b]; | |
| function hueToRGB(p, q, h) { | |
| if (h < 0) | |
| h += 1; | |
| else if (h > 1) | |
| h -= 1; | |
| if ((h * 6) < 1) | |
| return p + (q - p) * h * 6; | |
| else if ((h * 2) < 1) | |
| return q; | |
| else if ((h * 3) < 2) | |
| return p + (q - p) * ((2 / 3) - h) * 6; | |
| else | |
| return p; | |
| } | |
| }, | |
| _rgbaToHSLA: function(rgba, alpha) | |
| { | |
| var hsl = this._rgbToHSL(rgba) | |
| hsl.push(alpha); | |
| return hsl; | |
| }, | |
| _hslaToRGBA: function(hsla, alpha) | |
| { | |
| var rgb = this._hslToRGB(hsla); | |
| rgb.push(alpha); | |
| return rgb; | |
| }, | |
| _parse: function() | |
| { | |
| var value = this.value.toLowerCase().replace(/%|\s+/g, ""); | |
| if (value in WebInspector.Color.AdvancedNickNames) { | |
| this.format = "nickname"; | |
| var set = WebInspector.Color.AdvancedNickNames[value]; | |
| this.simple = false; | |
| this.rgba = set[0]; | |
| this.hsla = set[1]; | |
| this.nickname = set[2]; | |
| this.alpha = set[0][3]; | |
| return; | |
| } | |
| var simple = /^(?:#([0-9a-f]{3,6})|rgb\(([^)]+)\)|(\w+)|hsl\(([^)]+)\))$/i; | |
| var match = this.value.match(simple); | |
| if (match) { | |
| this.simple = true; | |
| if (match[1]) { | |
| var hex = match[1].toUpperCase(); | |
| if (hex.length === 3) { | |
| this.format = "shorthex"; | |
| this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2); | |
| } else { | |
| this.format = "hex"; | |
| this.hex = hex; | |
| } | |
| } else if (match[2]) { | |
| this.format = "rgb"; | |
| var rgb = match[2].split(/\s*,\s*/); | |
| this.rgb = rgb; | |
| this.hex = this._rgbStringsToHex(rgb); | |
| } else if (match[3]) { | |
| var nickname = match[3].toLowerCase(); | |
| if (nickname in WebInspector.Color.Nicknames) { | |
| this.format = "nickname"; | |
| this.hex = WebInspector.Color.Nicknames[nickname]; | |
| } else | |
| throw "unknown color name"; | |
| } else if (match[4]) { | |
| this.format = "hsl"; | |
| var hsl = match[4].replace(/%/g, "").split(/\s*,\s*/); | |
| this.hsl = hsl; | |
| this.rgb = this._hslToRGB(hsl); | |
| this.hex = this._rgbToHex(this.rgb); | |
| } | |
| var hex = this.hex; | |
| if (hex && hex in WebInspector.Color.HexTable) { | |
| var set = WebInspector.Color.HexTable[hex]; | |
| this.rgb = set[0]; | |
| this.hsl = set[1]; | |
| this.nickname = set[2]; | |
| } | |
| return; | |
| } | |
| var advanced = /^(?:rgba\(([^)]+)\)|hsla\(([^)]+)\))$/; | |
| match = this.value.match(advanced); | |
| if (match) { | |
| this.simple = false; | |
| if (match[1]) { | |
| this.format = "rgba"; | |
| this.rgba = match[1].split(/\s*,\s*/); | |
| this.rgba[3] = this.alpha = this._clamp(this.rgba[3], 0, 1); | |
| this.hsla = this._rgbaToHSLA(this.rgba, this.alpha); | |
| } else if (match[2]) { | |
| this.format = "hsla"; | |
| this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/); | |
| this.hsla[3] = this.alpha = this._clamp(this.hsla[3], 0, 1); | |
| this.rgba = this._hslaToRGBA(this.hsla, this.alpha); | |
| } | |
| return; | |
| } | |
| throw "could not parse color"; | |
| } | |
| } | |
| WebInspector.Color.HexTable = { | |
| "000000": [[0, 0, 0], [0, 0, 0], "black"], | |
| "000080": [[0, 0, 128], [240, 100, 25], "navy"], | |
| "00008B": [[0, 0, 139], [240, 100, 27], "darkBlue"], | |
| "0000CD": [[0, 0, 205], [240, 100, 40], "mediumBlue"], | |
| "0000FF": [[0, 0, 255], [240, 100, 50], "blue"], | |
| "006400": [[0, 100, 0], [120, 100, 20], "darkGreen"], | |
| "008000": [[0, 128, 0], [120, 100, 25], "green"], | |
| "008080": [[0, 128, 128], [180, 100, 25], "teal"], | |
| "008B8B": [[0, 139, 139], [180, 100, 27], "darkCyan"], | |
| "00BFFF": [[0, 191, 255], [195, 100, 50], "deepSkyBlue"], | |
| "00CED1": [[0, 206, 209], [181, 100, 41], "darkTurquoise"], | |
| "00FA9A": [[0, 250, 154], [157, 100, 49], "mediumSpringGreen"], | |
| "00FF00": [[0, 255, 0], [120, 100, 50], "lime"], | |
| "00FF7F": [[0, 255, 127], [150, 100, 50], "springGreen"], | |
| "00FFFF": [[0, 255, 255], [180, 100, 50], "cyan"], | |
| "191970": [[25, 25, 112], [240, 64, 27], "midnightBlue"], | |
| "1E90FF": [[30, 144, 255], [210, 100, 56], "dodgerBlue"], | |
| "20B2AA": [[32, 178, 170], [177, 70, 41], "lightSeaGreen"], | |
| "228B22": [[34, 139, 34], [120, 61, 34], "forestGreen"], | |
| "2E8B57": [[46, 139, 87], [146, 50, 36], "seaGreen"], | |
| "2F4F4F": [[47, 79, 79], [180, 25, 25], "darkSlateGray"], | |
| "32CD32": [[50, 205, 50], [120, 61, 50], "limeGreen"], | |
| "3CB371": [[60, 179, 113], [147, 50, 47], "mediumSeaGreen"], | |
| "40E0D0": [[64, 224, 208], [174, 72, 56], "turquoise"], | |
| "4169E1": [[65, 105, 225], [225, 73, 57], "royalBlue"], | |
| "4682B4": [[70, 130, 180], [207, 44, 49], "steelBlue"], | |
| "483D8B": [[72, 61, 139], [248, 39, 39], "darkSlateBlue"], | |
| "48D1CC": [[72, 209, 204], [178, 60, 55], "mediumTurquoise"], | |
| "4B0082": [[75, 0, 130], [275, 100, 25], "indigo"], | |
| "556B2F": [[85, 107, 47], [82, 39, 30], "darkOliveGreen"], | |
| "5F9EA0": [[95, 158, 160], [182, 25, 50], "cadetBlue"], | |
| "6495ED": [[100, 149, 237], [219, 79, 66], "cornflowerBlue"], | |
| "66CDAA": [[102, 205, 170], [160, 51, 60], "mediumAquaMarine"], | |
| "696969": [[105, 105, 105], [0, 0, 41], "dimGray"], | |
| "6A5ACD": [[106, 90, 205], [248, 53, 58], "slateBlue"], | |
| "6B8E23": [[107, 142, 35], [80, 60, 35], "oliveDrab"], | |
| "708090": [[112, 128, 144], [210, 13, 50], "slateGray"], | |
| "778899": [[119, 136, 153], [210, 14, 53], "lightSlateGray"], | |
| "7B68EE": [[123, 104, 238], [249, 80, 67], "mediumSlateBlue"], | |
| "7CFC00": [[124, 252, 0], [90, 100, 49], "lawnGreen"], | |
| "7FFF00": [[127, 255, 0], [90, 100, 50], "chartreuse"], | |
| "7FFFD4": [[127, 255, 212], [160, 100, 75], "aquamarine"], | |
| "800000": [[128, 0, 0], [0, 100, 25], "maroon"], | |
| "800080": [[128, 0, 128], [300, 100, 25], "purple"], | |
| "808000": [[128, 128, 0], [60, 100, 25], "olive"], | |
| "808080": [[128, 128, 128], [0, 0, 50], "gray"], | |
| "87CEEB": [[135, 206, 235], [197, 71, 73], "skyBlue"], | |
| "87CEFA": [[135, 206, 250], [203, 92, 75], "lightSkyBlue"], | |
| "8A2BE2": [[138, 43, 226], [271, 76, 53], "blueViolet"], | |
| "8B0000": [[139, 0, 0], [0, 100, 27], "darkRed"], | |
| "8B008B": [[139, 0, 139], [300, 100, 27], "darkMagenta"], | |
| "8B4513": [[139, 69, 19], [25, 76, 31], "saddleBrown"], | |
| "8FBC8F": [[143, 188, 143], [120, 25, 65], "darkSeaGreen"], | |
| "90EE90": [[144, 238, 144], [120, 73, 75], "lightGreen"], | |
| "9370D8": [[147, 112, 219], [260, 60, 65], "mediumPurple"], | |
| "9400D3": [[148, 0, 211], [282, 100, 41], "darkViolet"], | |
| "98FB98": [[152, 251, 152], [120, 93, 79], "paleGreen"], | |
| "9932CC": [[153, 50, 204], [280, 61, 50], "darkOrchid"], | |
| "9ACD32": [[154, 205, 50], [80, 61, 50], "yellowGreen"], | |
| "A0522D": [[160, 82, 45], [19, 56, 40], "sienna"], | |
| "A52A2A": [[165, 42, 42], [0, 59, 41], "brown"], | |
| "A9A9A9": [[169, 169, 169], [0, 0, 66], "darkGray"], | |
| "ADD8E6": [[173, 216, 230], [195, 53, 79], "lightBlue"], | |
| "ADFF2F": [[173, 255, 47], [84, 100, 59], "greenYellow"], | |
| "AFEEEE": [[175, 238, 238], [180, 65, 81], "paleTurquoise"], | |
| "B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"], | |
| "B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"], | |
| "B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"], | |
| "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenrod"], | |
| "BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"], | |
| "BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"], | |
| "BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"], | |
| "C0C0C0": [[192, 192, 192], [0, 0, 75], "silver"], | |
| "C71585": [[199, 21, 133], [322, 81, 43], "mediumVioletRed"], | |
| "CD5C5C": [[205, 92, 92], [0, 53, 58], "indianRed"], | |
| "CD853F": [[205, 133, 63], [30, 59, 53], "peru"], | |
| "D2691E": [[210, 105, 30], [25, 75, 47], "chocolate"], | |
| "D2B48C": [[210, 180, 140], [34, 44, 69], "tan"], | |
| "D3D3D3": [[211, 211, 211], [0, 0, 83], "lightGrey"], | |
| "D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"], | |
| "D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"], | |
| "DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"], | |
| "DAA520": [[218, 165, 32], [43, 74, 49], "goldenrod"], | |
| "DC143C": [[237, 164, 61], [35, 83, 58], "crimson"], | |
| "DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"], | |
| "DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"], | |
| "DEB887": [[222, 184, 135], [34, 57, 70], "burlyWood"], | |
| "E0FFFF": [[224, 255, 255], [180, 100, 94], "lightCyan"], | |
| "E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"], | |
| "E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"], | |
| "EE82EE": [[238, 130, 238], [300, 76, 72], "violet"], | |
| "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenrod"], | |
| "F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"], | |
| "F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"], | |
| "F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"], | |
| "F0FFF0": [[240, 255, 240], [120, 100, 97], "honeyDew"], | |
| "F0FFFF": [[240, 255, 255], [180, 100, 97], "azure"], | |
| "F4A460": [[244, 164, 96], [28, 87, 67], "sandyBrown"], | |
| "F5DEB3": [[245, 222, 179], [39, 77, 83], "wheat"], | |
| "F5F5DC": [[245, 245, 220], [60, 56, 91], "beige"], | |
| "F5F5F5": [[245, 245, 245], [0, 0, 96], "whiteSmoke"], | |
| "F5FFFA": [[245, 255, 250], [150, 100, 98], "mintCream"], | |
| "F8F8FF": [[248, 248, 255], [240, 100, 99], "ghostWhite"], | |
| "FA8072": [[250, 128, 114], [6, 93, 71], "salmon"], | |
| "FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"], | |
| "FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"], | |
| "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenrodYellow"], | |
| "FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"], | |
| "FF0000": [[255, 0, 0], [0, 100, 50], "red"], | |
| "FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"], | |
| "FF1493": [[255, 20, 147], [328, 100, 54], "deepPink"], | |
| "FF4500": [[255, 69, 0], [16, 100, 50], "orangeRed"], | |
| "FF6347": [[255, 99, 71], [9, 100, 64], "tomato"], | |
| "FF69B4": [[255, 105, 180], [330, 100, 71], "hotPink"], | |
| "FF7F50": [[255, 127, 80], [16, 100, 66], "coral"], | |
| "FF8C00": [[255, 140, 0], [33, 100, 50], "darkOrange"], | |
| "FFA07A": [[255, 160, 122], [17, 100, 74], "lightSalmon"], | |
| "FFA500": [[255, 165, 0], [39, 100, 50], "orange"], | |
| "FFB6C1": [[255, 182, 193], [351, 100, 86], "lightPink"], | |
| "FFC0CB": [[255, 192, 203], [350, 100, 88], "pink"], | |
| "FFD700": [[255, 215, 0], [51, 100, 50], "gold"], | |
| "FFDAB9": [[255, 218, 185], [28, 100, 86], "peachPuff"], | |
| "FFDEAD": [[255, 222, 173], [36, 100, 84], "navajoWhite"], | |
| "FFE4B5": [[255, 228, 181], [38, 100, 85], "moccasin"], | |
| "FFE4C4": [[255, 228, 196], [33, 100, 88], "bisque"], | |
| "FFE4E1": [[255, 228, 225], [6, 100, 94], "mistyRose"], | |
| "FFEBCD": [[255, 235, 205], [36, 100, 90], "blanchedAlmond"], | |
| "FFEFD5": [[255, 239, 213], [37, 100, 92], "papayaWhip"], | |
| "FFF0F5": [[255, 240, 245], [340, 100, 97], "lavenderBlush"], | |
| "FFF5EE": [[255, 245, 238], [25, 100, 97], "seaShell"], | |
| "FFF8DC": [[255, 248, 220], [48, 100, 93], "cornsilk"], | |
| "FFFACD": [[255, 250, 205], [54, 100, 90], "lemonChiffon"], | |
| "FFFAF0": [[255, 250, 240], [40, 100, 97], "floralWhite"], | |
| "FFFAFA": [[255, 250, 250], [0, 100, 99], "snow"], | |
| "FFFF00": [[255, 255, 0], [60, 100, 50], "yellow"], | |
| "FFFFE0": [[255, 255, 224], [60, 100, 94], "lightYellow"], | |
| "FFFFF0": [[255, 255, 240], [60, 100, 97], "ivory"], | |
| "FFFFFF": [[255, 255, 255], [0, 100, 100], "white"] | |
| }; | |
| WebInspector.Color.Nicknames = { | |
| "aliceblue": "F0F8FF", | |
| "antiquewhite": "FAEBD7", | |
| "aqua": "00FFFF", | |
| "aquamarine": "7FFFD4", | |
| "azure": "F0FFFF", | |
| "beige": "F5F5DC", | |
| "bisque": "FFE4C4", | |
| "black": "000000", | |
| "blanchedalmond": "FFEBCD", | |
| "blue": "0000FF", | |
| "blueviolet": "8A2BE2", | |
| "brown": "A52A2A", | |
| "burlywood": "DEB887", | |
| "cadetblue": "5F9EA0", | |
| "chartreuse": "7FFF00", | |
| "chocolate": "D2691E", | |
| "coral": "FF7F50", | |
| "cornflowerblue": "6495ED", | |
| "cornsilk": "FFF8DC", | |
| "crimson": "DC143C", | |
| "cyan": "00FFFF", | |
| "darkblue": "00008B", | |
| "darkcyan": "008B8B", | |
| "darkgoldenrod": "B8860B", | |
| "darkgray": "A9A9A9", | |
| "darkgreen": "006400", | |
| "darkkhaki": "BDB76B", | |
| "darkmagenta": "8B008B", | |
| "darkolivegreen": "556B2F", | |
| "darkorange": "FF8C00", | |
| "darkorchid": "9932CC", | |
| "darkred": "8B0000", | |
| "darksalmon": "E9967A", | |
| "darkseagreen": "8FBC8F", | |
| "darkslateblue": "483D8B", | |
| "darkslategray": "2F4F4F", | |
| "darkturquoise": "00CED1", | |
| "darkviolet": "9400D3", | |
| "deeppink": "FF1493", | |
| "deepskyblue": "00BFFF", | |
| "dimgray": "696969", | |
| "dodgerblue": "1E90FF", | |
| "firebrick": "B22222", | |
| "floralwhite": "FFFAF0", | |
| "forestgreen": "228B22", | |
| "fuchsia": "FF00FF", | |
| "gainsboro": "DCDCDC", | |
| "ghostwhite": "F8F8FF", | |
| "gold": "FFD700", | |
| "goldenrod": "DAA520", | |
| "gray": "808080", | |
| "green": "008000", | |
| "greenyellow": "ADFF2F", | |
| "honeydew": "F0FFF0", | |
| "hotpink": "FF69B4", | |
| "indianred": "CD5C5C", | |
| "indigo": "4B0082", | |
| "ivory": "FFFFF0", | |
| "khaki": "F0E68C", | |
| "lavender": "E6E6FA", | |
| "lavenderblush": "FFF0F5", | |
| "lawngreen": "7CFC00", | |
| "lemonchiffon": "FFFACD", | |
| "lightblue": "ADD8E6", | |
| "lightcoral": "F08080", | |
| "lightcyan": "E0FFFF", | |
| "lightgoldenrodyellow": "FAFAD2", | |
| "lightgreen": "90EE90", | |
| "lightgrey": "D3D3D3", | |
| "lightpink": "FFB6C1", | |
| "lightsalmon": "FFA07A", | |
| "lightseagreen": "20B2AA", | |
| "lightskyblue": "87CEFA", | |
| "lightslategray": "778899", | |
| "lightsteelblue": "B0C4DE", | |
| "lightyellow": "FFFFE0", | |
| "lime": "00FF00", | |
| "limegreen": "32CD32", | |
| "linen": "FAF0E6", | |
| "magenta": "FF00FF", | |
| "maroon": "800000", | |
| "mediumaquamarine": "66CDAA", | |
| "mediumblue": "0000CD", | |
| "mediumorchid": "BA55D3", | |
| "mediumpurple": "9370DB", | |
| "mediumseagreen": "3CB371", | |
| "mediumslateblue": "7B68EE", | |
| "mediumspringgreen": "00FA9A", | |
| "mediumturquoise": "48D1CC", | |
| "mediumvioletred": "C71585", | |
| "midnightblue": "191970", | |
| "mintcream": "F5FFFA", | |
| "mistyrose": "FFE4E1", | |
| "moccasin": "FFE4B5", | |
| "navajowhite": "FFDEAD", | |
| "navy": "000080", | |
| "oldlace": "FDF5E6", | |
| "olive": "808000", | |
| "olivedrab": "6B8E23", | |
| "orange": "FFA500", | |
| "orangered": "FF4500", | |
| "orchid": "DA70D6", | |
| "palegoldenrod": "EEE8AA", | |
| "palegreen": "98FB98", | |
| "paleturquoise": "AFEEEE", | |
| "palevioletred": "DB7093", | |
| "papayawhip": "FFEFD5", | |
| "peachpuff": "FFDAB9", | |
| "peru": "CD853F", | |
| "pink": "FFC0CB", | |
| "plum": "DDA0DD", | |
| "powderblue": "B0E0E6", | |
| "purple": "800080", | |
| "red": "FF0000", | |
| "rosybrown": "BC8F8F", | |
| "royalblue": "4169E1", | |
| "saddlebrown": "8B4513", | |
| "salmon": "FA8072", | |
| "sandybrown": "F4A460", | |
| "seagreen": "2E8B57", | |
| "seashell": "FFF5EE", | |
| "sienna": "A0522D", | |
| "silver": "C0C0C0", | |
| "skyblue": "87CEEB", | |
| "slateblue": "6A5ACD", | |
| "slategray": "708090", | |
| "snow": "FFFAFA", | |
| "springgreen": "00FF7F", | |
| "steelblue": "4682B4", | |
| "tan": "D2B48C", | |
| "teal": "008080", | |
| "thistle": "D8BFD8", | |
| "tomato": "FF6347", | |
| "turquoise": "40E0D0", | |
| "violet": "EE82EE", | |
| "wheat": "F5DEB3", | |
| "white": "FFFFFF", | |
| "whitesmoke": "F5F5F5", | |
| "yellow": "FFFF00", | |
| "yellowgreen": "9ACD32" | |
| }; | |
| WebInspector.Color.AdvancedNickNames = { | |
| "transparent": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], | |
| "rgba(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], | |
| "hsla(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], | |
| }; | |
| WebInspector.Color.PageHighlight = { | |
| Content: WebInspector.Color.fromRGBA(111, 168, 220, .66), | |
| ContentLight: WebInspector.Color.fromRGBA(111, 168, 220, .5), | |
| ContentOutline: WebInspector.Color.fromRGBA(9, 83, 148), | |
| Padding: WebInspector.Color.fromRGBA(147, 196, 125, .55), | |
| PaddingLight: WebInspector.Color.fromRGBA(147, 196, 125, .4), | |
| Border: WebInspector.Color.fromRGBA(255, 229, 153, .66), | |
| BorderLight: WebInspector.Color.fromRGBA(255, 229, 153, .5), | |
| Margin: WebInspector.Color.fromRGBA(246, 178, 107, .66), | |
| MarginLight: WebInspector.Color.fromRGBA(246, 178, 107, .5) | |
| } | |
| WebInspector.Color.Format = { | |
| Original: "original", | |
| Nickname: "nickname", | |
| HEX: "hex", | |
| ShortHEX: "shorthex", | |
| RGB: "rgb", | |
| RGBA: "rgba", | |
| HSL: "hsl", | |
| HSLA: "hsla" | |
| } | |
| WebInspector.CSSCompletions = function(properties, acceptEmptyPrefix) | |
| { | |
| this._values = []; | |
| this._longhands = {}; | |
| this._shorthands = {}; | |
| for (var i = 0; i < properties.length; ++i) { | |
| var property = properties[i]; | |
| if (typeof property === "string") { | |
| this._values.push(property); | |
| continue; | |
| } | |
| var propertyName = property.name; | |
| this._values.push(propertyName); | |
| var longhands = properties[i].longhands; | |
| if (longhands) { | |
| this._longhands[propertyName] = longhands; | |
| for (var j = 0; j < longhands.length; ++j) { | |
| var longhandName = longhands[j]; | |
| var shorthands = this._shorthands[longhandName]; | |
| if (!shorthands) { | |
| shorthands = []; | |
| this._shorthands[longhandName] = shorthands; | |
| } | |
| shorthands.push(propertyName); | |
| } | |
| } | |
| } | |
| this._values.sort(); | |
| this._acceptEmptyPrefix = acceptEmptyPrefix; | |
| } | |
| WebInspector.CSSCompletions.cssPropertiesMetainfo = null; | |
| WebInspector.CSSCompletions.requestCSSNameCompletions = function() | |
| { | |
| function propertyNamesCallback(error, properties) | |
| { | |
| if (!error) | |
| WebInspector.CSSCompletions.cssPropertiesMetainfo = new WebInspector.CSSCompletions(properties, false); | |
| } | |
| CSSAgent.getSupportedCSSProperties(propertyNamesCallback); | |
| } | |
| WebInspector.CSSCompletions.cssPropertiesMetainfoKeySet = function() | |
| { | |
| if (!WebInspector.CSSCompletions._cssPropertiesMetainfoKeySet) | |
| WebInspector.CSSCompletions._cssPropertiesMetainfoKeySet = WebInspector.CSSCompletions.cssPropertiesMetainfo.keySet(); | |
| return WebInspector.CSSCompletions._cssPropertiesMetainfoKeySet; | |
| } | |
| WebInspector.CSSCompletions.prototype = { | |
| startsWith: function(prefix) | |
| { | |
| var firstIndex = this._firstIndexOfPrefix(prefix); | |
| if (firstIndex === -1) | |
| return []; | |
| var results = []; | |
| while (firstIndex < this._values.length && this._values[firstIndex].startsWith(prefix)) | |
| results.push(this._values[firstIndex++]); | |
| return results; | |
| }, | |
| firstStartsWith: function(prefix) | |
| { | |
| var foundIndex = this._firstIndexOfPrefix(prefix); | |
| return (foundIndex === -1 ? "" : this._values[foundIndex]); | |
| }, | |
| _firstIndexOfPrefix: function(prefix) | |
| { | |
| if (!this._values.length) | |
| return -1; | |
| if (!prefix) | |
| return this._acceptEmptyPrefix ? 0 : -1; | |
| var maxIndex = this._values.length - 1; | |
| var minIndex = 0; | |
| var foundIndex; | |
| do { | |
| var middleIndex = (maxIndex + minIndex) >> 1; | |
| if (this._values[middleIndex].startsWith(prefix)) { | |
| foundIndex = middleIndex; | |
| break; | |
| } | |
| if (this._values[middleIndex] < prefix) | |
| minIndex = middleIndex + 1; | |
| else | |
| maxIndex = middleIndex - 1; | |
| } while (minIndex <= maxIndex); | |
| if (foundIndex === undefined) | |
| return -1; | |
| while (foundIndex && this._values[foundIndex - 1].startsWith(prefix)) | |
| foundIndex--; | |
| return foundIndex; | |
| }, | |
| keySet: function() | |
| { | |
| if (!this._keySet) | |
| this._keySet = this._values.keySet(); | |
| return this._keySet; | |
| }, | |
| next: function(str, prefix) | |
| { | |
| return this._closest(str, prefix, 1); | |
| }, | |
| previous: function(str, prefix) | |
| { | |
| return this._closest(str, prefix, -1); | |
| }, | |
| _closest: function(str, prefix, shift) | |
| { | |
| if (!str) | |
| return ""; | |
| var index = this._values.indexOf(str); | |
| if (index === -1) | |
| return ""; | |
| if (!prefix) { | |
| index = (index + this._values.length + shift) % this._values.length; | |
| return this._values[index]; | |
| } | |
| var propertiesWithPrefix = this.startsWith(prefix); | |
| var j = propertiesWithPrefix.indexOf(str); | |
| j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length; | |
| return propertiesWithPrefix[j]; | |
| }, | |
| longhands: function(shorthand) | |
| { | |
| return this._longhands[shorthand]; | |
| }, | |
| shorthands: function(longhand) | |
| { | |
| return this._shorthands[longhand]; | |
| } | |
| } | |
| WebInspector.CSSKeywordCompletions = {} | |
| WebInspector.CSSKeywordCompletions.forProperty = function(propertyName) | |
| { | |
| var acceptedKeywords = ["initial"]; | |
| if (propertyName in WebInspector.CSSKeywordCompletions._propertyKeywordMap) | |
| acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._propertyKeywordMap[propertyName]); | |
| if (propertyName in WebInspector.CSSKeywordCompletions._colorAwareProperties) | |
| acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._colors); | |
| if (propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties) | |
| acceptedKeywords.push("inherit"); | |
| return new WebInspector.CSSCompletions(acceptedKeywords, true); | |
| } | |
| WebInspector.CSSKeywordCompletions.isColorAwareProperty = function(propertyName) | |
| { | |
| return WebInspector.CSSKeywordCompletions._colorAwareProperties[propertyName] === true; | |
| } | |
| WebInspector.CSSKeywordCompletions.colors = function() | |
| { | |
| if (!WebInspector.CSSKeywordCompletions._colorsKeySet) | |
| WebInspector.CSSKeywordCompletions._colorsKeySet = WebInspector.CSSKeywordCompletions._colors.keySet(); | |
| return WebInspector.CSSKeywordCompletions._colorsKeySet; | |
| } | |
| WebInspector.CSSKeywordCompletions.InheritedProperties = [ | |
| "azimuth", "border-collapse", "border-spacing", "caption-side", "color", "cursor", "direction", "elevation", | |
| "empty-cells", "font-family", "font-size", "font-style", "font-variant", "font-weight", "font", "letter-spacing", | |
| "line-height", "list-style-image", "list-style-position", "list-style-type", "list-style", "orphans", "pitch-range", | |
| "pitch", "quotes", "richness", "speak-header", "speak-numeral", "speak-punctuation", "speak", "speech-rate", "stress", | |
| "text-align", "text-indent", "text-transform", "text-shadow", "visibility", "voice-family", "volume", "white-space", "widows", "word-spacing" | |
| ].keySet(); | |
| WebInspector.CSSKeywordCompletions._colors = [ | |
| "aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red", | |
| "silver", "teal", "white", "yellow", "transparent", "currentcolor", "grey", "aliceblue", "antiquewhite", | |
| "aquamarine", "azure", "beige", "bisque", "blanchedalmond", "blueviolet", "brown", "burlywood", "cadetblue", | |
| "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", | |
| "darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", | |
| "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey", | |
| "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick", | |
| "floralwhite", "forestgreen", "gainsboro", "ghostwhite", "gold", "goldenrod", "greenyellow", "honeydew", "hotpink", | |
| "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", | |
| "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink", | |
| "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", "lightyellow", | |
| "limegreen", "linen", "magenta", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", | |
| "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", | |
| "mistyrose", "moccasin", "navajowhite", "oldlace", "olivedrab", "orangered", "orchid", "palegoldenrod", "palegreen", | |
| "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "rosybrown", | |
| "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "skyblue", "slateblue", | |
| "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "thistle", "tomato", "turquoise", "violet", | |
| "wheat", "whitesmoke", "yellowgreen" | |
| ]; | |
| WebInspector.CSSKeywordCompletions._colorAwareProperties = [ | |
| "background", "background-color", "background-image", "border", "border-color", "border-top", "border-right", "border-bottom", | |
| "border-left", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "box-shadow", "color", | |
| "fill", "outline", "outline-color", "stroke", "text-line-through", "text-line-through-color", "text-overline", "text-overline-color", | |
| "text-shadow", "text-underline", "text-underline-color", "-webkit-box-shadow", "-webkit-text-emphasis", "-webkit-text-emphasis-color" | |
| ].keySet(); | |
| WebInspector.CSSKeywordCompletions._propertyKeywordMap = { | |
| "table-layout": [ | |
| "auto", "fixed" | |
| ], | |
| "visibility": [ | |
| "hidden", "visible", "collapse" | |
| ], | |
| "background-repeat": [ | |
| "repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round" | |
| ], | |
| "text-underline": [ | |
| "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" | |
| ], | |
| "content": [ | |
| "list-item", "close-quote", "no-close-quote", "no-open-quote", "open-quote" | |
| ], | |
| "list-style-image": [ | |
| "none" | |
| ], | |
| "clear": [ | |
| "none", "left", "right", "both" | |
| ], | |
| "text-underline-mode": [ | |
| "continuous", "skip-white-space" | |
| ], | |
| "overflow-x": [ | |
| "hidden", "auto", "visible", "overlay", "scroll" | |
| ], | |
| "stroke-linejoin": [ | |
| "round", "miter", "bevel" | |
| ], | |
| "baseline-shift": [ | |
| "baseline", "sub", "super" | |
| ], | |
| "border-bottom-width": [ | |
| "medium", "thick", "thin" | |
| ], | |
| "marquee-speed": [ | |
| "normal", "slow", "fast" | |
| ], | |
| "margin-top-collapse": [ | |
| "collapse", "separate", "discard" | |
| ], | |
| "max-height": [ | |
| "none" | |
| ], | |
| "box-orient": [ | |
| "horizontal", "vertical", "inline-axis", "block-axis" | |
| ], | |
| "font-stretch": [ | |
| "normal", "wider", "narrower", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", | |
| "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" | |
| ], | |
| "-webkit-color-correction": [ | |
| "default", "srgb" | |
| ], | |
| "text-underline-style": [ | |
| "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" | |
| ], | |
| "text-overline-mode": [ | |
| "continuous", "skip-white-space" | |
| ], | |
| "-webkit-background-composite": [ | |
| "highlight", "clear", "copy", "source-over", "source-in", "source-out", "source-atop", "destination-over", | |
| "destination-in", "destination-out", "destination-atop", "xor", "plus-darker", "plus-lighter" | |
| ], | |
| "border-left-width": [ | |
| "medium", "thick", "thin" | |
| ], | |
| "-webkit-writing-mode": [ | |
| "lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr", "horizontal-bt" | |
| ], | |
| "text-line-through-mode": [ | |
| "continuous", "skip-white-space" | |
| ], | |
| "border-collapse": [ | |
| "collapse", "separate" | |
| ], | |
| "page-break-inside": [ | |
| "auto", "avoid" | |
| ], | |
| "border-top-width": [ | |
| "medium", "thick", "thin" | |
| ], | |
| "outline-color": [ | |
| "invert" | |
| ], | |
| "text-line-through-style": [ | |
| "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" | |
| ], | |
| "outline-style": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "cursor": [ | |
| "none", "copy", "auto", "crosshair", "default", "pointer", "move", "vertical-text", "cell", "context-menu", | |
| "alias", "progress", "no-drop", "not-allowed", "-webkit-zoom-in", "-webkit-zoom-out", "e-resize", "ne-resize", | |
| "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "ew-resize", "ns-resize", | |
| "nesw-resize", "nwse-resize", "col-resize", "row-resize", "text", "wait", "help", "all-scroll", "-webkit-grab", | |
| "-webkit-grabbing" | |
| ], | |
| "border-width": [ | |
| "medium", "thick", "thin" | |
| ], | |
| "size": [ | |
| "a3", "a4", "a5", "b4", "b5", "landscape", "ledger", "legal", "letter", "portrait" | |
| ], | |
| "background-size": [ | |
| "contain", "cover" | |
| ], | |
| "direction": [ | |
| "ltr", "rtl" | |
| ], | |
| "marquee-direction": [ | |
| "left", "right", "auto", "reverse", "forwards", "backwards", "ahead", "up", "down" | |
| ], | |
| "enable-background": [ | |
| "accumulate", "new" | |
| ], | |
| "float": [ | |
| "none", "left", "right" | |
| ], | |
| "overflow-y": [ | |
| "hidden", "auto", "visible", "overlay", "scroll" | |
| ], | |
| "margin-bottom-collapse": [ | |
| "collapse", "separate", "discard" | |
| ], | |
| "box-reflect": [ | |
| "left", "right", "above", "below" | |
| ], | |
| "overflow": [ | |
| "hidden", "auto", "visible", "overlay", "scroll" | |
| ], | |
| "text-rendering": [ | |
| "auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision" | |
| ], | |
| "text-align": [ | |
| "-webkit-auto", "left", "right", "center", "justify", "-webkit-left", "-webkit-right", "-webkit-center" | |
| ], | |
| "list-style-position": [ | |
| "outside", "inside" | |
| ], | |
| "margin-bottom": [ | |
| "auto" | |
| ], | |
| "color-interpolation": [ | |
| "linearrgb" | |
| ], | |
| "background-origin": [ | |
| "border-box", "content-box", "padding-box" | |
| ], | |
| "word-wrap": [ | |
| "normal", "break-word" | |
| ], | |
| "font-weight": [ | |
| "normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900" | |
| ], | |
| "margin-before-collapse": [ | |
| "collapse", "separate", "discard" | |
| ], | |
| "text-overline-width": [ | |
| "normal", "medium", "auto", "thick", "thin" | |
| ], | |
| "text-transform": [ | |
| "none", "capitalize", "uppercase", "lowercase" | |
| ], | |
| "border-right-style": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "border-left-style": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "-webkit-text-emphasis": [ | |
| "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame" | |
| ], | |
| "font-style": [ | |
| "italic", "oblique", "normal" | |
| ], | |
| "speak": [ | |
| "none", "normal", "spell-out", "digits", "literal-punctuation", "no-punctuation" | |
| ], | |
| "text-line-through": [ | |
| "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave", "continuous", | |
| "skip-white-space" | |
| ], | |
| "color-rendering": [ | |
| "auto", "optimizeSpeed", "optimizeQuality" | |
| ], | |
| "list-style-type": [ | |
| "none", "disc", "circle", "square", "decimal", "decimal-leading-zero", "arabic-indic", "binary", "bengali", | |
| "cambodian", "khmer", "devanagari", "gujarati", "gurmukhi", "kannada", "lower-hexadecimal", "lao", "malayalam", | |
| "mongolian", "myanmar", "octal", "oriya", "persian", "urdu", "telugu", "tibetan", "thai", "upper-hexadecimal", | |
| "lower-roman", "upper-roman", "lower-greek", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "afar", | |
| "ethiopic-halehame-aa-et", "ethiopic-halehame-aa-er", "amharic", "ethiopic-halehame-am-et", "amharic-abegede", | |
| "ethiopic-abegede-am-et", "cjk-earthly-branch", "cjk-heavenly-stem", "ethiopic", "ethiopic-halehame-gez", | |
| "ethiopic-abegede", "ethiopic-abegede-gez", "hangul-consonant", "hangul", "lower-norwegian", "oromo", | |
| "ethiopic-halehame-om-et", "sidama", "ethiopic-halehame-sid-et", "somali", "ethiopic-halehame-so-et", "tigre", | |
| "ethiopic-halehame-tig", "tigrinya-er", "ethiopic-halehame-ti-er", "tigrinya-er-abegede", | |
| "ethiopic-abegede-ti-er", "tigrinya-et", "ethiopic-halehame-ti-et", "tigrinya-et-abegede", | |
| "ethiopic-abegede-ti-et", "upper-greek", "upper-norwegian", "asterisks", "footnotes", "hebrew", "armenian", | |
| "lower-armenian", "upper-armenian", "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha", | |
| "katakana-iroha" | |
| ], | |
| "-webkit-text-combine": [ | |
| "none", "horizontal" | |
| ], | |
| "outline": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "font": [ | |
| "caption", "icon", "menu", "message-box", "small-caption", "-webkit-mini-control", "-webkit-small-control", | |
| "-webkit-control", "status-bar", "italic", "oblique", "small-caps", "normal", "bold", "bolder", "lighter", | |
| "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium", | |
| "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", "larger", "serif", "sans-serif", "cursive", | |
| "fantasy", "monospace", "-webkit-body", "-webkit-pictograph" | |
| ], | |
| "dominant-baseline": [ | |
| "middle", "auto", "central", "text-before-edge", "text-after-edge", "ideographic", "alphabetic", "hanging", | |
| "mathematical", "use-script", "no-change", "reset-size" | |
| ], | |
| "display": [ | |
| "none", "inline", "block", "list-item", "run-in", "compact", "inline-block", "table", "inline-table", | |
| "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", | |
| "table-column", "table-cell", "table-caption", "-webkit-box", "-webkit-inline-box", "-wap-marquee" | |
| ], | |
| "-webkit-text-emphasis-position": [ | |
| "over", "under" | |
| ], | |
| "image-rendering": [ | |
| "auto", "optimizeSpeed", "optimizeQuality" | |
| ], | |
| "alignment-baseline": [ | |
| "baseline", "middle", "auto", "before-edge", "after-edge", "central", "text-before-edge", "text-after-edge", | |
| "ideographic", "alphabetic", "hanging", "mathematical" | |
| ], | |
| "outline-width": [ | |
| "medium", "thick", "thin" | |
| ], | |
| "text-line-through-width": [ | |
| "normal", "medium", "auto", "thick", "thin" | |
| ], | |
| "box-align": [ | |
| "baseline", "center", "stretch", "start", "end" | |
| ], | |
| "border-right-width": [ | |
| "medium", "thick", "thin" | |
| ], | |
| "border-top-style": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "line-height": [ | |
| "normal" | |
| ], | |
| "text-overflow": [ | |
| "clip", "ellipsis" | |
| ], | |
| "box-direction": [ | |
| "normal", "reverse" | |
| ], | |
| "margin-after-collapse": [ | |
| "collapse", "separate", "discard" | |
| ], | |
| "page-break-before": [ | |
| "left", "right", "auto", "always", "avoid" | |
| ], | |
| "-webkit-hyphens": [ | |
| "none", "auto", "manual" | |
| ], | |
| "border-image": [ | |
| "repeat", "stretch" | |
| ], | |
| "text-decoration": [ | |
| "blink", "line-through", "overline", "underline" | |
| ], | |
| "position": [ | |
| "absolute", "fixed", "relative", "static" | |
| ], | |
| "font-family": [ | |
| "serif", "sans-serif", "cursive", "fantasy", "monospace", "-webkit-body", "-webkit-pictograph" | |
| ], | |
| "text-overflow-mode": [ | |
| "clip", "ellipsis" | |
| ], | |
| "border-bottom-style": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "unicode-bidi": [ | |
| "normal", "bidi-override", "embed" | |
| ], | |
| "clip-rule": [ | |
| "nonzero", "evenodd" | |
| ], | |
| "margin-left": [ | |
| "auto" | |
| ], | |
| "margin-top": [ | |
| "auto" | |
| ], | |
| "zoom": [ | |
| "document", "reset" | |
| ], | |
| "text-overline-style": [ | |
| "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" | |
| ], | |
| "max-width": [ | |
| "none" | |
| ], | |
| "empty-cells": [ | |
| "hide", "show" | |
| ], | |
| "pointer-events": [ | |
| "none", "all", "auto", "visible", "visiblepainted", "visiblefill", "visiblestroke", "painted", "fill", "stroke" | |
| ], | |
| "letter-spacing": [ | |
| "normal" | |
| ], | |
| "background-clip": [ | |
| "border-box", "content-box", "padding-box" | |
| ], | |
| "-webkit-font-smoothing": [ | |
| "none", "auto", "antialiased", "subpixel-antialiased" | |
| ], | |
| "border": [ | |
| "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" | |
| ], | |
| "font-size": [ | |
| "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", | |
| "larger" | |
| ], | |
| "font-variant": [ | |
| "small-caps", "normal" | |
| ], | |
| "vertical-align": [ | |
| "baseline", "middle", "sub", "super", "text-top", "text-bottom", "top", "bottom", "-webkit-baseline-middle" | |
| ], | |
| "marquee-style": [ | |
| "none", "scroll", "slide", "alternate" | |
| ], | |
| "white-space": [ | |
| "normal", "nowrap", "pre", "pre-line", "pre-wrap" | |
| ], | |
| "text-underline-width": [ | |
| "normal", "medium", "auto", "thick", "thin" | |
| ], | |
| "box-lines": [ | |
| "single", "multiple" | |
| ], | |
| "page-break-after": [ | |
| "left", "right", "auto", "always", "avoid" | |
| ], | |
| "clip-path": [ | |
| "none" | |
| ], | |
| "margin": [ | |
| "auto" | |
| ], | |
| "marquee-repetition": [ | |
| "infinite" | |
| ], | |
| "margin-right": [ | |
| "auto" | |
| ], | |
| "-webkit-text-emphasis-style": [ | |
| "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame" | |
| ], | |
| "-webkit-transform": [ | |
| "scale", "scaleX", "scaleY", "scale3d", "rotate", "rotateX", "rotateY", "rotateZ", "rotate3d", "skew", "skewX", "skewY", | |
| "translate", "translateX", "translateY", "translateZ", "translate3d", "matrix", "matrix3d", "perspective" | |
| ] | |
| } | |
| WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle) | |
| { | |
| WebInspector.View.call(this); | |
| this.registerRequiredCSS("panelEnablerView.css"); | |
| this.element.addStyleClass("panel-enabler-view"); | |
| this.element.addStyleClass(identifier); | |
| this.contentElement = document.createElement("div"); | |
| this.contentElement.className = "panel-enabler-view-content"; | |
| this.element.appendChild(this.contentElement); | |
| this.imageElement = document.createElement("img"); | |
| this.contentElement.appendChild(this.imageElement); | |
| this.choicesForm = document.createElement("form"); | |
| this.contentElement.appendChild(this.choicesForm); | |
| this.headerElement = document.createElement("h1"); | |
| this.headerElement.textContent = headingText; | |
| this.choicesForm.appendChild(this.headerElement); | |
| var self = this; | |
| function enableOption(text, checked) { | |
| var label = document.createElement("label"); | |
| var option = document.createElement("input"); | |
| option.type = "radio"; | |
| option.name = "enable-option"; | |
| if (checked) | |
| option.checked = true; | |
| label.appendChild(option); | |
| label.appendChild(document.createTextNode(text)); | |
| self.choicesForm.appendChild(label); | |
| return option; | |
| }; | |
| this.enabledForSession = enableOption(WebInspector.UIString("Only enable for this session"), true); | |
| this.enabledAlways = enableOption(WebInspector.UIString("Always enable"), false); | |
| this.disclaimerElement = document.createElement("div"); | |
| this.disclaimerElement.className = "panel-enabler-disclaimer"; | |
| this.disclaimerElement.textContent = disclaimerText; | |
| this.choicesForm.appendChild(this.disclaimerElement); | |
| this.enableButton = document.createElement("button"); | |
| this.enableButton.setAttribute("type", "button"); | |
| this.enableButton.textContent = buttonTitle; | |
| this.enableButton.addEventListener("click", this._enableButtonCicked.bind(this), false); | |
| this.choicesForm.appendChild(this.enableButton); | |
| } | |
| WebInspector.PanelEnablerView.prototype = { | |
| _enableButtonCicked: function() | |
| { | |
| this.dispatchEventToListeners("enable clicked"); | |
| }, | |
| onResize: function() | |
| { | |
| this.imageElement.removeStyleClass("hidden"); | |
| if (this.element.offsetWidth < (this.choicesForm.offsetWidth + this.imageElement.offsetWidth)) | |
| this.imageElement.addStyleClass("hidden"); | |
| }, | |
| get alwaysEnabled() { | |
| return this.enabledAlways.checked; | |
| } | |
| } | |
| WebInspector.PanelEnablerView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.StatusBarButton = function(title, className, states) | |
| { | |
| this.element = document.createElement("button"); | |
| this.element.className = className + " status-bar-item"; | |
| this.element.addEventListener("click", this._clicked.bind(this), false); | |
| this.glyph = document.createElement("div"); | |
| this.glyph.className = "glyph"; | |
| this.element.appendChild(this.glyph); | |
| this.glyphShadow = document.createElement("div"); | |
| this.glyphShadow.className = "glyph shadow"; | |
| this.element.appendChild(this.glyphShadow); | |
| this.states = states; | |
| if (!states) | |
| this.states = 2; | |
| if (states == 2) | |
| this._state = false; | |
| else | |
| this._state = 0; | |
| this.title = title; | |
| this.disabled = false; | |
| this._visible = true; | |
| } | |
| WebInspector.StatusBarButton.width = 31; | |
| WebInspector.StatusBarButton.prototype = { | |
| _clicked: function() | |
| { | |
| this.dispatchEventToListeners("click"); | |
| if (this._showOptionsTimer) | |
| clearTimeout(this._showOptionsTimer); | |
| }, | |
| get disabled() | |
| { | |
| return this._disabled; | |
| }, | |
| set disabled(x) | |
| { | |
| if (this._disabled === x) | |
| return; | |
| this._disabled = x; | |
| this.element.disabled = x; | |
| }, | |
| get title() | |
| { | |
| return this._title; | |
| }, | |
| set title(x) | |
| { | |
| if (this._title === x) | |
| return; | |
| this._title = x; | |
| this.element.title = x; | |
| }, | |
| get state() | |
| { | |
| return this._state; | |
| }, | |
| set state(x) | |
| { | |
| if (this._state === x) | |
| return; | |
| if (this.states === 2) { | |
| if (x) | |
| this.element.addStyleClass("toggled-on"); | |
| else | |
| this.element.removeStyleClass("toggled-on"); | |
| } else { | |
| if (x !== 0) { | |
| this.element.removeStyleClass("toggled-" + this._state); | |
| this.element.addStyleClass("toggled-" + x); | |
| } else | |
| this.element.removeStyleClass("toggled-" + this._state); | |
| } | |
| this._state = x; | |
| }, | |
| get toggled() | |
| { | |
| if (this.states !== 2) | |
| throw("Only used toggled when there are 2 states, otherwise, use state"); | |
| return this.state; | |
| }, | |
| set toggled(x) | |
| { | |
| if (this.states !== 2) | |
| throw("Only used toggled when there are 2 states, otherwise, use state"); | |
| this.state = x; | |
| }, | |
| get visible() | |
| { | |
| return this._visible; | |
| }, | |
| set visible(x) | |
| { | |
| if (this._visible === x) | |
| return; | |
| if (x) | |
| this.element.removeStyleClass("hidden"); | |
| else | |
| this.element.addStyleClass("hidden"); | |
| this._visible = x; | |
| }, | |
| makeLongClickEnabled: function(buttonsProvider) | |
| { | |
| this.longClickGlyph = document.createElement("div"); | |
| this.longClickGlyph.className = "fill long-click-glyph"; | |
| this.element.appendChild(this.longClickGlyph); | |
| this.longClickGlyphShadow = document.createElement("div"); | |
| this.longClickGlyphShadow.className = "fill long-click-glyph shadow"; | |
| this.element.appendChild(this.longClickGlyphShadow); | |
| this.element.addEventListener("mousedown", mouseDown.bind(this), false); | |
| this.element.addEventListener("mouseout", mouseUp.bind(this), false); | |
| this.element.addEventListener("mouseup", mouseUp.bind(this), false); | |
| function mouseDown(e) | |
| { | |
| if (e.which !== 1) | |
| return; | |
| this._showOptionsTimer = setTimeout(this._showOptions.bind(this, buttonsProvider), 200); | |
| } | |
| function mouseUp(e) | |
| { | |
| if (e.which !== 1) | |
| return; | |
| if (this._showOptionsTimer) | |
| clearTimeout(this._showOptionsTimer); | |
| } | |
| }, | |
| _showOptions: function(buttonsProvider) | |
| { | |
| var buttons = buttonsProvider(); | |
| var mouseUpListener = mouseUp.bind(this); | |
| document.documentElement.addEventListener("mouseup", mouseUpListener, false); | |
| var optionsGlassPane = new WebInspector.GlassPane(); | |
| var optionsBarElement = optionsGlassPane.element.createChild("div", "alternate-status-bar-buttons-bar"); | |
| const buttonHeight = 24; | |
| optionsBarElement.style.height = (buttonHeight * buttons.length) + "px"; | |
| optionsBarElement.style.left = (this.element.offsetLeft + 1) + "px"; | |
| var boundMouseOver = mouseOver.bind(this); | |
| var boundMouseOut = mouseOut.bind(this); | |
| for (var i = 0; i < buttons.length; ++i) { | |
| buttons[i].element.addEventListener("mousemove", boundMouseOver.bind(this), false); | |
| buttons[i].element.addEventListener("mouseout", boundMouseOut.bind(this), false); | |
| optionsBarElement.appendChild(buttons[i].element); | |
| } | |
| buttons[buttons.length - 1].element.addStyleClass("emulate-active"); | |
| function mouseOver(e) | |
| { | |
| if (e.which !== 1) | |
| return; | |
| var buttonElement = e.target.enclosingNodeOrSelfWithClass("status-bar-item"); | |
| buttonElement.addStyleClass("emulate-active"); | |
| } | |
| function mouseOut(e) | |
| { | |
| if (e.which !== 1) | |
| return; | |
| var buttonElement = e.target.enclosingNodeOrSelfWithClass("status-bar-item"); | |
| buttonElement.removeStyleClass("emulate-active"); | |
| } | |
| function mouseUp(e) | |
| { | |
| if (e.which !== 1) | |
| return; | |
| optionsGlassPane.dispose(); | |
| document.documentElement.removeEventListener("mouseup", mouseUpListener, false); | |
| for (var i = 0; i < buttons.length; ++i) { | |
| if (buttons[i].element.hasStyleClass("emulate-active")) | |
| buttons[i]._clicked(); | |
| } | |
| } | |
| } | |
| } | |
| WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.StatusBarComboBox = function(changeHandler, className) | |
| { | |
| this.element = document.createElement("span"); | |
| this.element.className = "status-bar-select-container"; | |
| this._selectElement = this.element.createChild("select", "status-bar-item"); | |
| if (changeHandler) | |
| this._selectElement.addEventListener("change", changeHandler, false); | |
| if (className) | |
| this._selectElement.addStyleClass(className); | |
| } | |
| WebInspector.StatusBarComboBox.prototype = { | |
| addOption: function(option) | |
| { | |
| this._selectElement.appendChild(option); | |
| }, | |
| removeOption: function(option) | |
| { | |
| this._selectElement.removeChild(option); | |
| }, | |
| removeOptions: function() | |
| { | |
| this._selectElement.removeChildren(); | |
| }, | |
| selectedOption: function() | |
| { | |
| if (this._selectElement.selectedIndex >= 0) | |
| return this._selectElement[this._selectElement.selectedIndex]; | |
| return null; | |
| }, | |
| select: function(option) | |
| { | |
| this._selectElement.selectedIndex = Array.prototype.indexOf.call(this._selectElement, option); | |
| } | |
| } | |
| WebInspector.TextEditor = function() { }; | |
| WebInspector.TextEditor.Events = { | |
| GutterClick: "gutterClick" | |
| }; | |
| WebInspector.TextEditor.prototype = { | |
| set mimeType(mimeType) { }, | |
| setReadOnly: function(readOnly) { }, | |
| readOnly: function() { }, | |
| defaultFocusedElement: function() { }, | |
| revealLine: function(lineNumber) { }, | |
| addBreakpoint: function(lineNumber, disabled, conditional) { }, | |
| removeBreakpoint: function(lineNumber) { }, | |
| setExecutionLine: function(lineNumber) { }, | |
| clearExecutionLine: function() { }, | |
| addDecoration: function(lineNumber, element) { }, | |
| removeDecoration: function(lineNumber, element) { }, | |
| markAndRevealRange: function(range) { }, | |
| highlightLine: function(lineNumber) { }, | |
| clearLineHighlight: function() { }, | |
| elementsToRestoreScrollPositionsFor: function() { }, | |
| inheritScrollPositions: function(textEditor) { }, | |
| beginUpdates: function() { }, | |
| endUpdates: function() { }, | |
| onResize: function() { }, | |
| editRange: function(range, text) { }, | |
| scrollToLine: function(lineNumber) { }, | |
| selection: function(textRange) { }, | |
| lastSelection: function() { }, | |
| setSelection: function(textRange) { }, | |
| setText: function(text) { }, | |
| text: function() { }, | |
| range: function() { }, | |
| line: function(lineNumber) { }, | |
| get linesCount() { }, | |
| setAttribute: function(line, name, value) { }, | |
| getAttribute: function(line, name) { }, | |
| removeAttribute: function(line, name) { }, | |
| wasShown: function() { }, | |
| willHide: function() { } | |
| } | |
| WebInspector.TextEditorDelegate = function() | |
| { | |
| } | |
| WebInspector.TextEditorDelegate.prototype = { | |
| onTextChanged: function(oldRange, newRange) { }, | |
| selectionChanged: function(textRange) { }, | |
| scrollChanged: function(lineNumber) { }, | |
| populateLineGutterContextMenu: function(contextMenu, lineNumber) { }, | |
| populateTextAreaContextMenu: function(contextMenu, lineNumber) { }, | |
| createLink: function(hrefValue, isExternal) { } | |
| } | |
| WebInspector.DefaultTextEditor = function(url, delegate) | |
| { | |
| WebInspector.View.call(this); | |
| this._delegate = delegate; | |
| this._url = url; | |
| this.registerRequiredCSS("textEditor.css"); | |
| this.element.className = "text-editor monospace"; | |
| this._textModel = new WebInspector.TextEditorModel(); | |
| this._textModel.addEventListener(WebInspector.TextEditorModel.Events.TextChanged, this._textChanged, this); | |
| this._textModel.resetUndoStack(); | |
| var enterTextChangeMode = this._enterInternalTextChangeMode.bind(this); | |
| var exitTextChangeMode = this._exitInternalTextChangeMode.bind(this); | |
| var syncScrollListener = this._syncScroll.bind(this); | |
| var syncDecorationsForLineListener = this._syncDecorationsForLine.bind(this); | |
| var syncLineHeightListener = this._syncLineHeight.bind(this); | |
| this._mainPanel = new WebInspector.TextEditorMainPanel(this._delegate, this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode); | |
| this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener, syncLineHeightListener); | |
| this._mainPanel.element.addEventListener("scroll", this._handleScrollChanged.bind(this), false); | |
| this._mainPanel._container.addEventListener("focus", this._handleFocused.bind(this), false); | |
| this._gutterPanel.element.addEventListener("mousedown", this._onMouseDown.bind(this), true); | |
| this.element.appendChild(this._mainPanel.element); | |
| this.element.appendChild(this._gutterPanel.element); | |
| function forwardWheelEvent(event) | |
| { | |
| var clone = document.createEvent("WheelEvent"); | |
| clone.initWebKitWheelEvent(event.wheelDeltaX, event.wheelDeltaY, | |
| event.view, | |
| event.screenX, event.screenY, | |
| event.clientX, event.clientY, | |
| event.ctrlKey, event.altKey, event.shiftKey, event.metaKey); | |
| this._mainPanel.element.dispatchEvent(clone); | |
| } | |
| this._gutterPanel.element.addEventListener("mousewheel", forwardWheelEvent.bind(this), false); | |
| this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); | |
| this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); | |
| this._registerShortcuts(); | |
| } | |
| WebInspector.DefaultTextEditor.prototype = { | |
| set mimeType(mimeType) | |
| { | |
| this._mainPanel.mimeType = mimeType; | |
| }, | |
| setReadOnly: function(readOnly) | |
| { | |
| if (this._mainPanel.readOnly() === readOnly) | |
| return; | |
| this._mainPanel.setReadOnly(readOnly, this.isShowing()); | |
| WebInspector.markBeingEdited(this.element, !readOnly); | |
| }, | |
| readOnly: function() | |
| { | |
| return this._mainPanel.readOnly(); | |
| }, | |
| get textModel() | |
| { | |
| return this._textModel; | |
| }, | |
| defaultFocusedElement: function() | |
| { | |
| return this._mainPanel.defaultFocusedElement(); | |
| }, | |
| revealLine: function(lineNumber) | |
| { | |
| this._mainPanel.revealLine(lineNumber); | |
| }, | |
| _onMouseDown: function(event) | |
| { | |
| var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); | |
| if (!target) | |
| return; | |
| this.dispatchEventToListeners(WebInspector.TextEditor.Events.GutterClick, { lineNumber: target.lineNumber, event: event }); | |
| }, | |
| addBreakpoint: function(lineNumber, disabled, conditional) | |
| { | |
| this.beginUpdates(); | |
| this._gutterPanel.addDecoration(lineNumber, "webkit-breakpoint"); | |
| if (disabled) | |
| this._gutterPanel.addDecoration(lineNumber, "webkit-breakpoint-disabled"); | |
| else | |
| this._gutterPanel.removeDecoration(lineNumber, "webkit-breakpoint-disabled"); | |
| if (conditional) | |
| this._gutterPanel.addDecoration(lineNumber, "webkit-breakpoint-conditional"); | |
| else | |
| this._gutterPanel.removeDecoration(lineNumber, "webkit-breakpoint-conditional"); | |
| this.endUpdates(); | |
| }, | |
| removeBreakpoint: function(lineNumber) | |
| { | |
| this.beginUpdates(); | |
| this._gutterPanel.removeDecoration(lineNumber, "webkit-breakpoint"); | |
| this._gutterPanel.removeDecoration(lineNumber, "webkit-breakpoint-disabled"); | |
| this._gutterPanel.removeDecoration(lineNumber, "webkit-breakpoint-conditional"); | |
| this.endUpdates(); | |
| }, | |
| setExecutionLine: function(lineNumber) | |
| { | |
| this._executionLineNumber = lineNumber; | |
| this._mainPanel.addDecoration(lineNumber, "webkit-execution-line"); | |
| this._gutterPanel.addDecoration(lineNumber, "webkit-execution-line"); | |
| }, | |
| clearExecutionLine: function() | |
| { | |
| if (typeof this._executionLineNumber === "number") { | |
| this._mainPanel.removeDecoration(this._executionLineNumber, "webkit-execution-line"); | |
| this._gutterPanel.removeDecoration(this._executionLineNumber, "webkit-execution-line"); | |
| } | |
| delete this._executionLineNumber; | |
| }, | |
| addDecoration: function(lineNumber, element) | |
| { | |
| this._mainPanel.addDecoration(lineNumber, element); | |
| this._gutterPanel.addDecoration(lineNumber, element); | |
| }, | |
| removeDecoration: function(lineNumber, element) | |
| { | |
| this._mainPanel.removeDecoration(lineNumber, element); | |
| this._gutterPanel.removeDecoration(lineNumber, element); | |
| }, | |
| markAndRevealRange: function(range) | |
| { | |
| if (range) | |
| this.setSelection(range); | |
| this._mainPanel.markAndRevealRange(range); | |
| }, | |
| highlightLine: function(lineNumber) | |
| { | |
| if (typeof lineNumber !== "number" || lineNumber < 0) | |
| return; | |
| lineNumber = Math.min(lineNumber, this._textModel.linesCount - 1); | |
| this._mainPanel.highlightLine(lineNumber); | |
| }, | |
| clearLineHighlight: function() | |
| { | |
| this._mainPanel.clearLineHighlight(); | |
| }, | |
| _freeCachedElements: function() | |
| { | |
| this._mainPanel._freeCachedElements(); | |
| this._gutterPanel._freeCachedElements(); | |
| }, | |
| elementsToRestoreScrollPositionsFor: function() | |
| { | |
| return [this._mainPanel.element]; | |
| }, | |
| inheritScrollPositions: function(textEditor) | |
| { | |
| this._mainPanel.element._scrollTop = textEditor._mainPanel.element.scrollTop; | |
| this._mainPanel.element._scrollLeft = textEditor._mainPanel.element.scrollLeft; | |
| }, | |
| beginUpdates: function() | |
| { | |
| this._mainPanel.beginUpdates(); | |
| this._gutterPanel.beginUpdates(); | |
| }, | |
| endUpdates: function() | |
| { | |
| this._mainPanel.endUpdates(); | |
| this._gutterPanel.endUpdates(); | |
| this._updatePanelOffsets(); | |
| }, | |
| onResize: function() | |
| { | |
| this._mainPanel.resize(); | |
| this._gutterPanel.resize(); | |
| this._updatePanelOffsets(); | |
| }, | |
| _textChanged: function(event) | |
| { | |
| if (!this._internalTextChangeMode) | |
| this._textModel.resetUndoStack(); | |
| this._mainPanel.textChanged(event.data.oldRange, event.data.newRange); | |
| this._gutterPanel.textChanged(event.data.oldRange, event.data.newRange); | |
| this._updatePanelOffsets(); | |
| }, | |
| editRange: function(range, text) | |
| { | |
| this._enterInternalTextChangeMode(); | |
| this._textModel.markUndoableState(); | |
| var newRange = this._textModel.editRange(range, text); | |
| this._exitInternalTextChangeMode(range, newRange); | |
| return newRange; | |
| }, | |
| _enterInternalTextChangeMode: function() | |
| { | |
| this._internalTextChangeMode = true; | |
| }, | |
| _exitInternalTextChangeMode: function(oldRange, newRange) | |
| { | |
| this._internalTextChangeMode = false; | |
| this._delegate.onTextChanged(oldRange, newRange); | |
| }, | |
| _updatePanelOffsets: function() | |
| { | |
| var lineNumbersWidth = this._gutterPanel.element.offsetWidth; | |
| if (lineNumbersWidth) | |
| this._mainPanel.element.style.setProperty("left", (lineNumbersWidth + 2) + "px"); | |
| else | |
| this._mainPanel.element.style.removeProperty("left"); | |
| }, | |
| _syncScroll: function() | |
| { | |
| var mainElement = this._mainPanel.element; | |
| var gutterElement = this._gutterPanel.element; | |
| this._gutterPanel.syncClientHeight(mainElement.clientHeight); | |
| gutterElement.scrollTop = mainElement.scrollTop; | |
| }, | |
| _syncDecorationsForLine: function(lineNumber) | |
| { | |
| if (lineNumber >= this._textModel.linesCount) | |
| return; | |
| var mainChunk = this._mainPanel.chunkForLine(lineNumber); | |
| if (mainChunk.linesCount === 1 && mainChunk.decorated) { | |
| var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber); | |
| var height = mainChunk.height; | |
| if (height) | |
| gutterChunk.element.style.setProperty("height", height + "px"); | |
| else | |
| gutterChunk.element.style.removeProperty("height"); | |
| } else { | |
| var gutterChunk = this._gutterPanel.chunkForLine(lineNumber); | |
| if (gutterChunk.linesCount === 1) | |
| gutterChunk.element.style.removeProperty("height"); | |
| } | |
| }, | |
| _syncLineHeight: function(gutterRow) | |
| { | |
| if (this._lineHeightSynced) | |
| return; | |
| if (gutterRow && gutterRow.offsetHeight) { | |
| this.element.style.setProperty("line-height", gutterRow.offsetHeight + "px"); | |
| this._lineHeightSynced = true; | |
| } | |
| }, | |
| _registerShortcuts: function() | |
| { | |
| var keys = WebInspector.KeyboardShortcut.Keys; | |
| var modifiers = WebInspector.KeyboardShortcut.Modifiers; | |
| this._shortcuts = {}; | |
| var handleEnterKey = this._mainPanel.handleEnterKey.bind(this._mainPanel); | |
| this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Enter.code, WebInspector.KeyboardShortcut.Modifiers.None)] = handleEnterKey; | |
| var handleUndo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, false); | |
| var handleRedo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, true); | |
| this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.CtrlOrMeta)] = handleUndo; | |
| this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.Shift | modifiers.CtrlOrMeta)] = handleRedo; | |
| var handleTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, false); | |
| var handleShiftTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, true); | |
| this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code)] = handleTabKey; | |
| this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code, modifiers.Shift)] = handleShiftTabKey; | |
| }, | |
| _handleKeyDown: function(e) | |
| { | |
| if (this.readOnly()) | |
| return; | |
| var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e); | |
| var handler = this._shortcuts[shortcutKey]; | |
| if (handler && handler()) | |
| e.consume(true); | |
| }, | |
| _contextMenu: function(event) | |
| { | |
| var anchor = event.target.enclosingNodeOrSelfWithNodeName("a"); | |
| if (anchor) | |
| return; | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); | |
| if (target) | |
| this._delegate.populateLineGutterContextMenu(contextMenu, target.lineNumber); | |
| else { | |
| target = this._mainPanel._enclosingLineRowOrSelf(event.target); | |
| this._delegate.populateTextAreaContextMenu(contextMenu, target && target.lineNumber); | |
| } | |
| contextMenu.show(event); | |
| }, | |
| _handleScrollChanged: function(event) | |
| { | |
| var visibleFrom = this._mainPanel.element.scrollTop; | |
| var firstVisibleLineNumber = this._mainPanel._findFirstVisibleLineNumber(visibleFrom); | |
| this._delegate.scrollChanged(firstVisibleLineNumber); | |
| }, | |
| scrollToLine: function(lineNumber) | |
| { | |
| this._mainPanel.scrollToLine(lineNumber); | |
| }, | |
| _handleSelectionChange: function(event) | |
| { | |
| var textRange = this._mainPanel._getSelection(); | |
| if (textRange) { | |
| this._lastSelection = WebInspector.TextRange.createFromLocation(textRange.endLine, textRange.endColumn); | |
| } | |
| this._delegate.selectionChanged(textRange); | |
| }, | |
| selection: function(textRange) | |
| { | |
| return this._mainPanel._getSelection(); | |
| }, | |
| lastSelection: function() | |
| { | |
| return this._lastSelection; | |
| }, | |
| setSelection: function(textRange) | |
| { | |
| this._lastSelection = textRange; | |
| if (this.element.isAncestor(document.activeElement)) | |
| this._mainPanel._restoreSelection(textRange); | |
| }, | |
| setText: function(text) | |
| { | |
| this._textModel.setText(text); | |
| }, | |
| text: function() | |
| { | |
| return this._textModel.text(); | |
| }, | |
| range: function() | |
| { | |
| return this._textModel.range(); | |
| }, | |
| line: function(lineNumber) | |
| { | |
| return this._textModel.line(lineNumber); | |
| }, | |
| get linesCount() | |
| { | |
| return this._textModel.linesCount; | |
| }, | |
| setAttribute: function(line, name, value) | |
| { | |
| this._textModel.setAttribute(line, name, value); | |
| }, | |
| getAttribute: function(line, name) | |
| { | |
| return this._textModel.getAttribute(line, name); | |
| }, | |
| removeAttribute: function(line, name) | |
| { | |
| this._textModel.removeAttribute(line, name); | |
| }, | |
| wasShown: function() | |
| { | |
| if (!this.readOnly()) | |
| WebInspector.markBeingEdited(this.element, true); | |
| this._boundSelectionChangeListener = this._handleSelectionChange.bind(this); | |
| document.addEventListener("selectionchange", this._boundSelectionChangeListener, false); | |
| }, | |
| _handleFocused: function() | |
| { | |
| if (this._lastSelection) | |
| this.setSelection(this._lastSelection); | |
| }, | |
| willHide: function() | |
| { | |
| document.removeEventListener("selectionchange", this._boundSelectionChangeListener, false); | |
| delete this._boundSelectionChangeListener; | |
| if (!this.readOnly()) | |
| WebInspector.markBeingEdited(this.element, false); | |
| this._freeCachedElements(); | |
| } | |
| } | |
| WebInspector.DefaultTextEditor.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.TextEditorChunkedPanel = function(textModel) | |
| { | |
| this._textModel = textModel; | |
| this._defaultChunkSize = 50; | |
| this._paintCoalescingLevel = 0; | |
| this._domUpdateCoalescingLevel = 0; | |
| } | |
| WebInspector.TextEditorChunkedPanel.prototype = { | |
| get textModel() | |
| { | |
| return this._textModel; | |
| }, | |
| scrollToLine: function(lineNumber) | |
| { | |
| if (lineNumber >= this._textModel.linesCount) | |
| return; | |
| var chunk = this.makeLineAChunk(lineNumber); | |
| this.element.scrollTop = chunk.offsetTop; | |
| }, | |
| revealLine: function(lineNumber) | |
| { | |
| if (lineNumber >= this._textModel.linesCount) | |
| return; | |
| var chunk = this.makeLineAChunk(lineNumber); | |
| chunk.element.scrollIntoViewIfNeeded(); | |
| }, | |
| addDecoration: function(lineNumber, decoration) | |
| { | |
| if (lineNumber >= this._textModel.linesCount) | |
| return; | |
| var chunk = this.makeLineAChunk(lineNumber); | |
| chunk.addDecoration(decoration); | |
| }, | |
| removeDecoration: function(lineNumber, decoration) | |
| { | |
| if (lineNumber >= this._textModel.linesCount) | |
| return; | |
| var chunk = this.chunkForLine(lineNumber); | |
| chunk.removeDecoration(decoration); | |
| }, | |
| _buildChunks: function() | |
| { | |
| this.beginDomUpdates(); | |
| this._container.removeChildren(); | |
| this._textChunks = []; | |
| for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) { | |
| var chunk = this._createNewChunk(i, i + this._defaultChunkSize); | |
| this._textChunks.push(chunk); | |
| this._container.appendChild(chunk.element); | |
| } | |
| this._repaintAll(); | |
| this.endDomUpdates(); | |
| }, | |
| makeLineAChunk: function(lineNumber) | |
| { | |
| var chunkNumber = this._chunkNumberForLine(lineNumber); | |
| var oldChunk = this._textChunks[chunkNumber]; | |
| if (!oldChunk) { | |
| console.error("No chunk for line number: " + lineNumber); | |
| return; | |
| } | |
| if (oldChunk.linesCount === 1) | |
| return oldChunk; | |
| return this._splitChunkOnALine(lineNumber, chunkNumber, true); | |
| }, | |
| _splitChunkOnALine: function(lineNumber, chunkNumber, createSuffixChunk) | |
| { | |
| this.beginDomUpdates(); | |
| var oldChunk = this._textChunks[chunkNumber]; | |
| var wasExpanded = oldChunk.expanded; | |
| oldChunk.expanded = false; | |
| var insertIndex = chunkNumber + 1; | |
| if (lineNumber > oldChunk.startLine) { | |
| var prefixChunk = this._createNewChunk(oldChunk.startLine, lineNumber); | |
| prefixChunk.readOnly = oldChunk.readOnly; | |
| this._textChunks.splice(insertIndex++, 0, prefixChunk); | |
| this._container.insertBefore(prefixChunk.element, oldChunk.element); | |
| } | |
| var endLine = createSuffixChunk ? lineNumber + 1 : oldChunk.startLine + oldChunk.linesCount; | |
| var lineChunk = this._createNewChunk(lineNumber, endLine); | |
| lineChunk.readOnly = oldChunk.readOnly; | |
| this._textChunks.splice(insertIndex++, 0, lineChunk); | |
| this._container.insertBefore(lineChunk.element, oldChunk.element); | |
| if (oldChunk.startLine + oldChunk.linesCount > endLine) { | |
| var suffixChunk = this._createNewChunk(endLine, oldChunk.startLine + oldChunk.linesCount); | |
| suffixChunk.readOnly = oldChunk.readOnly; | |
| this._textChunks.splice(insertIndex, 0, suffixChunk); | |
| this._container.insertBefore(suffixChunk.element, oldChunk.element); | |
| } | |
| this._textChunks.splice(chunkNumber, 1); | |
| this._container.removeChild(oldChunk.element); | |
| if (wasExpanded) { | |
| if (prefixChunk) | |
| prefixChunk.expanded = true; | |
| lineChunk.expanded = true; | |
| if (suffixChunk) | |
| suffixChunk.expanded = true; | |
| } | |
| this.endDomUpdates(); | |
| return lineChunk; | |
| }, | |
| _scroll: function() | |
| { | |
| this._scheduleRepaintAll(); | |
| if (this._syncScrollListener) | |
| this._syncScrollListener(); | |
| }, | |
| _scheduleRepaintAll: function() | |
| { | |
| if (this._repaintAllTimer) | |
| clearTimeout(this._repaintAllTimer); | |
| this._repaintAllTimer = setTimeout(this._repaintAll.bind(this), 50); | |
| }, | |
| beginUpdates: function() | |
| { | |
| this._paintCoalescingLevel++; | |
| }, | |
| endUpdates: function() | |
| { | |
| this._paintCoalescingLevel--; | |
| if (!this._paintCoalescingLevel) | |
| this._repaintAll(); | |
| }, | |
| beginDomUpdates: function() | |
| { | |
| this._domUpdateCoalescingLevel++; | |
| }, | |
| endDomUpdates: function() | |
| { | |
| this._domUpdateCoalescingLevel--; | |
| }, | |
| _chunkNumberForLine: function(lineNumber) | |
| { | |
| function compareLineNumbers(value, chunk) | |
| { | |
| return value < chunk.startLine ? -1 : 1; | |
| } | |
| var insertBefore = insertionIndexForObjectInListSortedByFunction(lineNumber, this._textChunks, compareLineNumbers); | |
| return insertBefore - 1; | |
| }, | |
| chunkForLine: function(lineNumber) | |
| { | |
| return this._textChunks[this._chunkNumberForLine(lineNumber)]; | |
| }, | |
| _findFirstVisibleChunkNumber: function(visibleFrom) | |
| { | |
| function compareOffsetTops(value, chunk) | |
| { | |
| return value < chunk.offsetTop ? -1 : 1; | |
| } | |
| var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, this._textChunks, compareOffsetTops); | |
| return insertBefore - 1; | |
| }, | |
| _findVisibleChunks: function(visibleFrom, visibleTo) | |
| { | |
| var from = this._findFirstVisibleChunkNumber(visibleFrom); | |
| for (var to = from + 1; to < this._textChunks.length; ++to) { | |
| if (this._textChunks[to].offsetTop >= visibleTo) | |
| break; | |
| } | |
| return { start: from, end: to }; | |
| }, | |
| _findFirstVisibleLineNumber: function(visibleFrom) | |
| { | |
| var chunk = this._textChunks[this._findFirstVisibleChunkNumber(visibleFrom)]; | |
| if (!chunk.expanded) | |
| return chunk.startLine; | |
| var lineNumbers = []; | |
| for (var i = 0; i < chunk.linesCount; ++i) { | |
| lineNumbers.push(chunk.startLine + i); | |
| } | |
| function compareLineRowOffsetTops(value, lineNumber) | |
| { | |
| var lineRow = chunk.getExpandedLineRow(lineNumber); | |
| return value < lineRow.offsetTop ? -1 : 1; | |
| } | |
| var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, lineNumbers, compareLineRowOffsetTops); | |
| return lineNumbers[insertBefore - 1]; | |
| }, | |
| _repaintAll: function() | |
| { | |
| delete this._repaintAllTimer; | |
| if (this._paintCoalescingLevel || this._dirtyLines) | |
| return; | |
| var visibleFrom = this.element.scrollTop; | |
| var visibleTo = this.element.scrollTop + this.element.clientHeight; | |
| if (visibleTo) { | |
| var result = this._findVisibleChunks(visibleFrom, visibleTo); | |
| this._expandChunks(result.start, result.end); | |
| } | |
| }, | |
| _expandChunks: function(fromIndex, toIndex) | |
| { | |
| for (var i = 0; i < fromIndex; ++i) | |
| this._textChunks[i].expanded = false; | |
| for (var i = toIndex; i < this._textChunks.length; ++i) | |
| this._textChunks[i].expanded = false; | |
| for (var i = fromIndex; i < toIndex; ++i) | |
| this._textChunks[i].expanded = true; | |
| }, | |
| _totalHeight: function(firstElement, lastElement) | |
| { | |
| lastElement = (lastElement || firstElement).nextElementSibling; | |
| if (lastElement) | |
| return lastElement.offsetTop - firstElement.offsetTop; | |
| var offsetParent = firstElement.offsetParent; | |
| if (offsetParent && offsetParent.scrollHeight > offsetParent.clientHeight) | |
| return offsetParent.scrollHeight - firstElement.offsetTop; | |
| var total = 0; | |
| while (firstElement && firstElement !== lastElement) { | |
| total += firstElement.offsetHeight; | |
| firstElement = firstElement.nextElementSibling; | |
| } | |
| return total; | |
| }, | |
| resize: function() | |
| { | |
| this._repaintAll(); | |
| } | |
| } | |
| WebInspector.TextEditorGutterPanel = function(textModel, syncDecorationsForLineListener, syncLineHeightListener) | |
| { | |
| WebInspector.TextEditorChunkedPanel.call(this, textModel); | |
| this._syncDecorationsForLineListener = syncDecorationsForLineListener; | |
| this._syncLineHeightListener = syncLineHeightListener; | |
| this.element = document.createElement("div"); | |
| this.element.className = "text-editor-lines"; | |
| this._container = document.createElement("div"); | |
| this._container.className = "inner-container"; | |
| this.element.appendChild(this._container); | |
| this.element.addEventListener("scroll", this._scroll.bind(this), false); | |
| this._freeCachedElements(); | |
| this._buildChunks(); | |
| this._decorations = {}; | |
| } | |
| WebInspector.TextEditorGutterPanel.prototype = { | |
| _freeCachedElements: function() | |
| { | |
| this._cachedRows = []; | |
| }, | |
| _createNewChunk: function(startLine, endLine) | |
| { | |
| return new WebInspector.TextEditorGutterChunk(this, startLine, endLine); | |
| }, | |
| textChanged: function(oldRange, newRange) | |
| { | |
| this.beginDomUpdates(); | |
| var linesDiff = newRange.linesCount - oldRange.linesCount; | |
| if (linesDiff) { | |
| for (var chunkNumber = this._textChunks.length - 1; chunkNumber >= 0 ; --chunkNumber) { | |
| var chunk = this._textChunks[chunkNumber]; | |
| if (chunk.startLine + chunk.linesCount <= this._textModel.linesCount) | |
| break; | |
| chunk.expanded = false; | |
| this._container.removeChild(chunk.element); | |
| } | |
| this._textChunks.length = chunkNumber + 1; | |
| var totalLines = 0; | |
| if (this._textChunks.length) { | |
| var lastChunk = this._textChunks[this._textChunks.length - 1]; | |
| totalLines = lastChunk.startLine + lastChunk.linesCount; | |
| } | |
| for (var i = totalLines; i < this._textModel.linesCount; i += this._defaultChunkSize) { | |
| var chunk = this._createNewChunk(i, i + this._defaultChunkSize); | |
| this._textChunks.push(chunk); | |
| this._container.appendChild(chunk.element); | |
| } | |
| for (var lineNumber in this._decorations) { | |
| lineNumber = parseInt(lineNumber, 10); | |
| if (lineNumber < oldRange.startLine) | |
| continue; | |
| if (lineNumber === oldRange.startLine && oldRange.startColumn) | |
| continue; | |
| var lineDecorationsCopy = this._decorations[lineNumber].slice(); | |
| for (var i = 0; i < lineDecorationsCopy.length; ++i) { | |
| var decoration = lineDecorationsCopy[i]; | |
| this.removeDecoration(lineNumber, decoration); | |
| if (lineNumber < oldRange.endLine) | |
| continue; | |
| this.addDecoration(lineNumber + linesDiff, decoration); | |
| } | |
| } | |
| this._repaintAll(); | |
| } else { | |
| var chunkNumber = this._chunkNumberForLine(newRange.startLine); | |
| var chunk = this._textChunks[chunkNumber]; | |
| while (chunk && chunk.startLine <= newRange.endLine) { | |
| if (chunk.linesCount === 1) | |
| this._syncDecorationsForLineListener(chunk.startLine); | |
| chunk = this._textChunks[++chunkNumber]; | |
| } | |
| } | |
| this.endDomUpdates(); | |
| }, | |
| syncClientHeight: function(clientHeight) | |
| { | |
| if (this.element.offsetHeight > clientHeight) | |
| this._container.style.setProperty("padding-bottom", (this.element.offsetHeight - clientHeight) + "px"); | |
| else | |
| this._container.style.removeProperty("padding-bottom"); | |
| }, | |
| addDecoration: function(lineNumber, decoration) | |
| { | |
| WebInspector.TextEditorChunkedPanel.prototype.addDecoration.call(this, lineNumber, decoration); | |
| var decorations = this._decorations[lineNumber]; | |
| if (!decorations) { | |
| decorations = []; | |
| this._decorations[lineNumber] = decorations; | |
| } | |
| decorations.push(decoration); | |
| }, | |
| removeDecoration: function(lineNumber, decoration) | |
| { | |
| WebInspector.TextEditorChunkedPanel.prototype.removeDecoration.call(this, lineNumber, decoration); | |
| var decorations = this._decorations[lineNumber]; | |
| if (decorations) { | |
| decorations.remove(decoration); | |
| if (!decorations.length) | |
| delete this._decorations[lineNumber]; | |
| } | |
| } | |
| } | |
| WebInspector.TextEditorGutterPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype; | |
| WebInspector.TextEditorGutterChunk = function(textEditor, startLine, endLine) | |
| { | |
| this._textEditor = textEditor; | |
| this._textModel = textEditor._textModel; | |
| this.startLine = startLine; | |
| endLine = Math.min(this._textModel.linesCount, endLine); | |
| this.linesCount = endLine - startLine; | |
| this._expanded = false; | |
| this.element = document.createElement("div"); | |
| this.element.lineNumber = startLine; | |
| this.element.className = "webkit-line-number"; | |
| if (this.linesCount === 1) { | |
| var innerSpan = document.createElement("span"); | |
| innerSpan.className = "webkit-line-number-inner"; | |
| innerSpan.textContent = startLine + 1; | |
| var outerSpan = document.createElement("div"); | |
| outerSpan.className = "webkit-line-number-outer"; | |
| outerSpan.appendChild(innerSpan); | |
| this.element.appendChild(outerSpan); | |
| } else { | |
| var lineNumbers = []; | |
| for (var i = startLine; i < endLine; ++i) | |
| lineNumbers.push(i + 1); | |
| this.element.textContent = lineNumbers.join("\n"); | |
| } | |
| } | |
| WebInspector.TextEditorGutterChunk.prototype = { | |
| addDecoration: function(decoration) | |
| { | |
| this._textEditor.beginDomUpdates(); | |
| if (typeof decoration === "string") | |
| this.element.addStyleClass(decoration); | |
| this._textEditor.endDomUpdates(); | |
| }, | |
| removeDecoration: function(decoration) | |
| { | |
| this._textEditor.beginDomUpdates(); | |
| if (typeof decoration === "string") | |
| this.element.removeStyleClass(decoration); | |
| this._textEditor.endDomUpdates(); | |
| }, | |
| get expanded() | |
| { | |
| return this._expanded; | |
| }, | |
| set expanded(expanded) | |
| { | |
| if (this.linesCount === 1) | |
| this._textEditor._syncDecorationsForLineListener(this.startLine); | |
| if (this._expanded === expanded) | |
| return; | |
| this._expanded = expanded; | |
| if (this.linesCount === 1) | |
| return; | |
| this._textEditor.beginDomUpdates(); | |
| if (expanded) { | |
| this._expandedLineRows = []; | |
| var parentElement = this.element.parentElement; | |
| for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) { | |
| var lineRow = this._createRow(i); | |
| parentElement.insertBefore(lineRow, this.element); | |
| this._expandedLineRows.push(lineRow); | |
| } | |
| parentElement.removeChild(this.element); | |
| this._textEditor._syncLineHeightListener(this._expandedLineRows[0]); | |
| } else { | |
| var elementInserted = false; | |
| for (var i = 0; i < this._expandedLineRows.length; ++i) { | |
| var lineRow = this._expandedLineRows[i]; | |
| var parentElement = lineRow.parentElement; | |
| if (parentElement) { | |
| if (!elementInserted) { | |
| elementInserted = true; | |
| parentElement.insertBefore(this.element, lineRow); | |
| } | |
| parentElement.removeChild(lineRow); | |
| } | |
| this._textEditor._cachedRows.push(lineRow); | |
| } | |
| delete this._expandedLineRows; | |
| } | |
| this._textEditor.endDomUpdates(); | |
| }, | |
| get height() | |
| { | |
| if (!this._expandedLineRows) | |
| return this._textEditor._totalHeight(this.element); | |
| return this._textEditor._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]); | |
| }, | |
| get offsetTop() | |
| { | |
| return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop; | |
| }, | |
| _createRow: function(lineNumber) | |
| { | |
| var lineRow = this._textEditor._cachedRows.pop() || document.createElement("div"); | |
| lineRow.lineNumber = lineNumber; | |
| lineRow.className = "webkit-line-number"; | |
| lineRow.textContent = lineNumber + 1; | |
| return lineRow; | |
| } | |
| } | |
| WebInspector.TextEditorMainPanel = function(delegate, textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode) | |
| { | |
| WebInspector.TextEditorChunkedPanel.call(this, textModel); | |
| this._delegate = delegate; | |
| this._syncScrollListener = syncScrollListener; | |
| this._syncDecorationsForLineListener = syncDecorationsForLineListener; | |
| this._enterTextChangeMode = enterTextChangeMode; | |
| this._exitTextChangeMode = exitTextChangeMode; | |
| this._url = url; | |
| this._highlighter = new WebInspector.TextEditorHighlighter(textModel, this._highlightDataReady.bind(this)); | |
| this._readOnly = true; | |
| this.element = document.createElement("div"); | |
| this.element.className = "text-editor-contents"; | |
| this.element.tabIndex = 0; | |
| this._container = document.createElement("div"); | |
| this._container.className = "inner-container"; | |
| this._container.tabIndex = 0; | |
| this.element.appendChild(this._container); | |
| this.element.addEventListener("scroll", this._scroll.bind(this), false); | |
| this.element.addEventListener("focus", this._handleElementFocus.bind(this), false); | |
| this._handleDOMUpdatesCallback = this._handleDOMUpdates.bind(this); | |
| this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false); | |
| this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false); | |
| this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false); | |
| this._freeCachedElements(); | |
| this._buildChunks(); | |
| } | |
| WebInspector.TextEditorMainPanel.prototype = { | |
| set mimeType(mimeType) | |
| { | |
| this._highlighter.mimeType = mimeType; | |
| }, | |
| setReadOnly: function(readOnly, requestFocus) | |
| { | |
| if (this._readOnly === readOnly) | |
| return; | |
| this.beginDomUpdates(); | |
| this._readOnly = readOnly; | |
| if (this._readOnly) | |
| this._container.removeStyleClass("text-editor-editable"); | |
| else { | |
| this._container.addStyleClass("text-editor-editable"); | |
| if (requestFocus) | |
| this._updateSelectionOnStartEditing(); | |
| } | |
| this.endDomUpdates(); | |
| }, | |
| readOnly: function() | |
| { | |
| return this._readOnly; | |
| }, | |
| _handleElementFocus: function() | |
| { | |
| if (!this._readOnly) | |
| this._container.focus(); | |
| }, | |
| defaultFocusedElement: function() | |
| { | |
| if (this._readOnly) | |
| return this.element; | |
| return this._container; | |
| }, | |
| _updateSelectionOnStartEditing: function() | |
| { | |
| this._container.focus(); | |
| var selection = window.getSelection(); | |
| if (selection.rangeCount) { | |
| var commonAncestorContainer = selection.getRangeAt(0).commonAncestorContainer; | |
| if (this._container.isSelfOrAncestor(commonAncestorContainer)) | |
| return; | |
| } | |
| selection.removeAllRanges(); | |
| var range = document.createRange(); | |
| range.setStart(this._container, 0); | |
| range.setEnd(this._container, 0); | |
| selection.addRange(range); | |
| }, | |
| setEditableRange: function(startLine, endLine) | |
| { | |
| this.beginDomUpdates(); | |
| var firstChunkNumber = this._chunkNumberForLine(startLine); | |
| var firstChunk = this._textChunks[firstChunkNumber]; | |
| if (firstChunk.startLine !== startLine) { | |
| this._splitChunkOnALine(startLine, firstChunkNumber); | |
| firstChunkNumber += 1; | |
| } | |
| var lastChunkNumber = this._textChunks.length; | |
| if (endLine !== this._textModel.linesCount) { | |
| lastChunkNumber = this._chunkNumberForLine(endLine); | |
| var lastChunk = this._textChunks[lastChunkNumber]; | |
| if (lastChunk && lastChunk.startLine !== endLine) { | |
| this._splitChunkOnALine(endLine, lastChunkNumber); | |
| lastChunkNumber += 1; | |
| } | |
| } | |
| for (var chunkNumber = 0; chunkNumber < firstChunkNumber; ++chunkNumber) | |
| this._textChunks[chunkNumber].readOnly = true; | |
| for (var chunkNumber = firstChunkNumber; chunkNumber < lastChunkNumber; ++chunkNumber) | |
| this._textChunks[chunkNumber].readOnly = false; | |
| for (var chunkNumber = lastChunkNumber; chunkNumber < this._textChunks.length; ++chunkNumber) | |
| this._textChunks[chunkNumber].readOnly = true; | |
| this.endDomUpdates(); | |
| }, | |
| clearEditableRange: function() | |
| { | |
| for (var chunkNumber = 0; chunkNumber < this._textChunks.length; ++chunkNumber) | |
| this._textChunks[chunkNumber].readOnly = false; | |
| }, | |
| markAndRevealRange: function(range) | |
| { | |
| if (this._rangeToMark) { | |
| var markedLine = this._rangeToMark.startLine; | |
| delete this._rangeToMark; | |
| if (!this._dirtyLines) { | |
| this.beginDomUpdates(); | |
| var chunk = this.chunkForLine(markedLine); | |
| var wasExpanded = chunk.expanded; | |
| chunk.expanded = false; | |
| chunk.updateCollapsedLineRow(); | |
| chunk.expanded = wasExpanded; | |
| this.endDomUpdates(); | |
| } else | |
| this._paintLines(markedLine, markedLine + 1); | |
| } | |
| if (range) { | |
| this._rangeToMark = range; | |
| this.revealLine(range.startLine); | |
| var chunk = this.makeLineAChunk(range.startLine); | |
| this._paintLine(chunk.element); | |
| if (this._markedRangeElement) | |
| this._markedRangeElement.scrollIntoViewIfNeeded(); | |
| } | |
| delete this._markedRangeElement; | |
| }, | |
| highlightLine: function(lineNumber) | |
| { | |
| this.clearLineHighlight(); | |
| this._highlightedLine = lineNumber; | |
| this.revealLine(lineNumber); | |
| if (!this._readOnly) | |
| this._restoreSelection(WebInspector.TextRange.createFromLocation(lineNumber, 0), false); | |
| this.addDecoration(lineNumber, "webkit-highlighted-line"); | |
| }, | |
| clearLineHighlight: function() | |
| { | |
| if (typeof this._highlightedLine === "number") { | |
| this.removeDecoration(this._highlightedLine, "webkit-highlighted-line"); | |
| delete this._highlightedLine; | |
| } | |
| }, | |
| _freeCachedElements: function() | |
| { | |
| this._cachedSpans = []; | |
| this._cachedTextNodes = []; | |
| this._cachedRows = []; | |
| }, | |
| handleUndoRedo: function(redo) | |
| { | |
| if (this._dirtyLines) | |
| return false; | |
| this.beginUpdates(); | |
| function before() | |
| { | |
| this._enterTextChangeMode(); | |
| } | |
| function after(oldRange, newRange) | |
| { | |
| this._exitTextChangeMode(oldRange, newRange); | |
| } | |
| var range = redo ? this._textModel.redo(before.bind(this), after.bind(this)) : this._textModel.undo(before.bind(this), after.bind(this)); | |
| this.endUpdates(); | |
| if (range) | |
| this._restoreSelection(range, true); | |
| return true; | |
| }, | |
| handleTabKeyPress: function(shiftKey) | |
| { | |
| if (this._dirtyLines) | |
| return false; | |
| var selection = this._getSelection(); | |
| if (!selection) | |
| return false; | |
| var range = selection.normalize(); | |
| this.beginUpdates(); | |
| this._enterTextChangeMode(); | |
| var newRange; | |
| var rangeWasEmpty = range.isEmpty(); | |
| if (shiftKey) | |
| newRange = this._unindentLines(range); | |
| else { | |
| if (rangeWasEmpty) | |
| newRange = this._editRange(range, WebInspector.settings.textEditorIndent.get()); | |
| else | |
| newRange = this._indentLines(range); | |
| } | |
| this._exitTextChangeMode(range, newRange); | |
| this.endUpdates(); | |
| if (rangeWasEmpty) | |
| newRange.startColumn = newRange.endColumn; | |
| this._restoreSelection(newRange, true); | |
| return true; | |
| }, | |
| _indentLines: function(range) | |
| { | |
| var indent = WebInspector.settings.textEditorIndent.get(); | |
| if (this._lastEditedRange) | |
| this._textModel.markUndoableState(); | |
| var newRange = range.clone(); | |
| if (range.startColumn) | |
| newRange.startColumn += indent.length; | |
| var indentEndLine = range.endLine; | |
| if (range.endColumn) | |
| newRange.endColumn += indent.length; | |
| else | |
| indentEndLine--; | |
| for (var lineNumber = range.startLine; lineNumber <= indentEndLine; lineNumber++) | |
| this._textModel.editRange(WebInspector.TextRange.createFromLocation(lineNumber, 0), indent); | |
| this._lastEditedRange = newRange; | |
| return newRange; | |
| }, | |
| _unindentLines: function(range) | |
| { | |
| if (this._lastEditedRange) | |
| this._textModel.markUndoableState(); | |
| var indent = WebInspector.settings.textEditorIndent.get(); | |
| var indentLength = indent === WebInspector.TextEditorModel.Indent.TabCharacter ? 4 : indent.length; | |
| var lineIndentRegex = new RegExp("^ {1," + indentLength + "}"); | |
| var newRange = range.clone(); | |
| var indentEndLine = range.endLine; | |
| if (!range.endColumn) | |
| indentEndLine--; | |
| for (var lineNumber = range.startLine; lineNumber <= indentEndLine; lineNumber++) { | |
| var line = this._textModel.line(lineNumber); | |
| var firstCharacter = line.charAt(0); | |
| var lineIndentLength; | |
| if (firstCharacter === " ") | |
| lineIndentLength = line.match(lineIndentRegex)[0].length; | |
| else if (firstCharacter === "\t") | |
| lineIndentLength = 1; | |
| else | |
| continue; | |
| this._textModel.editRange(new WebInspector.TextRange(lineNumber, 0, lineNumber, lineIndentLength), ""); | |
| if (lineNumber === range.startLine) | |
| newRange.startColumn = Math.max(0, newRange.startColumn - lineIndentLength); | |
| } | |
| if (lineIndentLength) | |
| newRange.endColumn = Math.max(0, newRange.endColumn - lineIndentLength); | |
| this._lastEditedRange = newRange; | |
| return newRange; | |
| }, | |
| handleEnterKey: function() | |
| { | |
| if (this._dirtyLines) | |
| return false; | |
| var range = this._getSelection(); | |
| if (!range) | |
| return false; | |
| range = range.normalize(); | |
| if (range.endColumn === 0) | |
| return false; | |
| var line = this._textModel.line(range.startLine); | |
| var linePrefix = line.substring(0, range.startColumn); | |
| var indentMatch = linePrefix.match(/^\s+/); | |
| var currentIndent = indentMatch ? indentMatch[0] : ""; | |
| var textEditorIndent = WebInspector.settings.textEditorIndent.get(); | |
| var indent = WebInspector.TextEditorModel.endsWithBracketRegex.test(linePrefix) ? currentIndent + textEditorIndent : currentIndent; | |
| if (!indent) | |
| return false; | |
| this.beginUpdates(); | |
| this._enterTextChangeMode(); | |
| var lineBreak = this._textModel.lineBreak; | |
| var newRange; | |
| if (range.isEmpty() && line.substr(range.endColumn - 1, 2) === '{}') { | |
| newRange = this._editRange(range, lineBreak + indent + lineBreak + currentIndent); | |
| newRange.endLine--; | |
| newRange.endColumn += textEditorIndent.length; | |
| } else | |
| newRange = this._editRange(range, lineBreak + indent); | |
| this._exitTextChangeMode(range, newRange); | |
| this.endUpdates(); | |
| this._restoreSelection(newRange.collapseToEnd(), true); | |
| return true; | |
| }, | |
| _splitChunkOnALine: function(lineNumber, chunkNumber, createSuffixChunk) | |
| { | |
| var selection = this._getSelection(); | |
| var chunk = WebInspector.TextEditorChunkedPanel.prototype._splitChunkOnALine.call(this, lineNumber, chunkNumber, createSuffixChunk); | |
| this._restoreSelection(selection); | |
| return chunk; | |
| }, | |
| beginDomUpdates: function() | |
| { | |
| WebInspector.TextEditorChunkedPanel.prototype.beginDomUpdates.call(this); | |
| if (this._domUpdateCoalescingLevel === 1) { | |
| this._container.removeEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false); | |
| this._container.removeEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false); | |
| this._container.removeEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false); | |
| } | |
| }, | |
| endDomUpdates: function() | |
| { | |
| WebInspector.TextEditorChunkedPanel.prototype.endDomUpdates.call(this); | |
| if (this._domUpdateCoalescingLevel === 0) { | |
| this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false); | |
| this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false); | |
| this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false); | |
| } | |
| }, | |
| _buildChunks: function() | |
| { | |
| for (var i = 0; i < this._textModel.linesCount; ++i) | |
| this._textModel.removeAttribute(i, "highlight"); | |
| WebInspector.TextEditorChunkedPanel.prototype._buildChunks.call(this); | |
| }, | |
| _createNewChunk: function(startLine, endLine) | |
| { | |
| return new WebInspector.TextEditorMainChunk(this, startLine, endLine); | |
| }, | |
| _expandChunks: function(fromIndex, toIndex) | |
| { | |
| var lastChunk = this._textChunks[toIndex - 1]; | |
| var lastVisibleLine = lastChunk.startLine + lastChunk.linesCount; | |
| var selection = this._getSelection(); | |
| this._muteHighlightListener = true; | |
| this._highlighter.highlight(lastVisibleLine); | |
| delete this._muteHighlightListener; | |
| this._restorePaintLinesOperationsCredit(); | |
| WebInspector.TextEditorChunkedPanel.prototype._expandChunks.call(this, fromIndex, toIndex); | |
| this._adjustPaintLinesOperationsRefreshValue(); | |
| this._restoreSelection(selection); | |
| }, | |
| _highlightDataReady: function(fromLine, toLine) | |
| { | |
| if (this._muteHighlightListener) | |
| return; | |
| this._restorePaintLinesOperationsCredit(); | |
| this._paintLines(fromLine, toLine, true ); | |
| }, | |
| _schedulePaintLines: function(startLine, endLine) | |
| { | |
| if (startLine >= endLine) | |
| return; | |
| if (!this._scheduledPaintLines) { | |
| this._scheduledPaintLines = [ { startLine: startLine, endLine: endLine } ]; | |
| this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 0); | |
| } else { | |
| for (var i = 0; i < this._scheduledPaintLines.length; ++i) { | |
| var chunk = this._scheduledPaintLines[i]; | |
| if (chunk.startLine <= endLine && chunk.endLine >= startLine) { | |
| chunk.startLine = Math.min(chunk.startLine, startLine); | |
| chunk.endLine = Math.max(chunk.endLine, endLine); | |
| return; | |
| } | |
| if (chunk.startLine > endLine) { | |
| this._scheduledPaintLines.splice(i, 0, { startLine: startLine, endLine: endLine }); | |
| return; | |
| } | |
| } | |
| this._scheduledPaintLines.push({ startLine: startLine, endLine: endLine }); | |
| } | |
| }, | |
| _paintScheduledLines: function(skipRestoreSelection) | |
| { | |
| if (this._paintScheduledLinesTimer) | |
| clearTimeout(this._paintScheduledLinesTimer); | |
| delete this._paintScheduledLinesTimer; | |
| if (!this._scheduledPaintLines) | |
| return; | |
| if (this._dirtyLines || this._repaintAllTimer) { | |
| this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 50); | |
| return; | |
| } | |
| var scheduledPaintLines = this._scheduledPaintLines; | |
| delete this._scheduledPaintLines; | |
| this._restorePaintLinesOperationsCredit(); | |
| this._paintLineChunks(scheduledPaintLines, !skipRestoreSelection); | |
| this._adjustPaintLinesOperationsRefreshValue(); | |
| }, | |
| _restorePaintLinesOperationsCredit: function() | |
| { | |
| if (!this._paintLinesOperationsRefreshValue) | |
| this._paintLinesOperationsRefreshValue = 250; | |
| this._paintLinesOperationsCredit = this._paintLinesOperationsRefreshValue; | |
| this._paintLinesOperationsLastRefresh = Date.now(); | |
| }, | |
| _adjustPaintLinesOperationsRefreshValue: function() | |
| { | |
| var operationsDone = this._paintLinesOperationsRefreshValue - this._paintLinesOperationsCredit; | |
| if (operationsDone <= 0) | |
| return; | |
| var timePast = Date.now() - this._paintLinesOperationsLastRefresh; | |
| if (timePast <= 0) | |
| return; | |
| var value = Math.floor(operationsDone / timePast * 50); | |
| this._paintLinesOperationsRefreshValue = Number.constrain(value, 150, 1500); | |
| }, | |
| _paintLines: function(fromLine, toLine, restoreSelection) | |
| { | |
| this._paintLineChunks([ { startLine: fromLine, endLine: toLine } ], restoreSelection); | |
| }, | |
| _paintLineChunks: function(lineChunks, restoreSelection) | |
| { | |
| var visibleFrom = this.element.scrollTop; | |
| var firstVisibleLineNumber = this._findFirstVisibleLineNumber(visibleFrom); | |
| var chunk; | |
| var selection; | |
| var invisibleLineRows = []; | |
| for (var i = 0; i < lineChunks.length; ++i) { | |
| var lineChunk = lineChunks[i]; | |
| if (this._dirtyLines || this._scheduledPaintLines) { | |
| this._schedulePaintLines(lineChunk.startLine, lineChunk.endLine); | |
| continue; | |
| } | |
| for (var lineNumber = lineChunk.startLine; lineNumber < lineChunk.endLine; ++lineNumber) { | |
| if (!chunk || lineNumber < chunk.startLine || lineNumber >= chunk.startLine + chunk.linesCount) | |
| chunk = this.chunkForLine(lineNumber); | |
| var lineRow = chunk.getExpandedLineRow(lineNumber); | |
| if (!lineRow) | |
| continue; | |
| if (lineNumber < firstVisibleLineNumber) { | |
| invisibleLineRows.push(lineRow); | |
| continue; | |
| } | |
| if (restoreSelection && !selection) | |
| selection = this._getSelection(); | |
| this._paintLine(lineRow); | |
| if (this._paintLinesOperationsCredit < 0) { | |
| this._schedulePaintLines(lineNumber + 1, lineChunk.endLine); | |
| break; | |
| } | |
| } | |
| } | |
| for (var i = 0; i < invisibleLineRows.length; ++i) { | |
| if (restoreSelection && !selection) | |
| selection = this._getSelection(); | |
| this._paintLine(invisibleLineRows[i]); | |
| } | |
| if (restoreSelection) | |
| this._restoreSelection(selection); | |
| }, | |
| _paintLine: function(lineRow) | |
| { | |
| var lineNumber = lineRow.lineNumber; | |
| if (this._dirtyLines) { | |
| this._schedulePaintLines(lineNumber, lineNumber + 1); | |
| return; | |
| } | |
| this.beginDomUpdates(); | |
| try { | |
| if (this._scheduledPaintLines || this._paintLinesOperationsCredit < 0) { | |
| this._schedulePaintLines(lineNumber, lineNumber + 1); | |
| return; | |
| } | |
| var highlight = this._textModel.getAttribute(lineNumber, "highlight"); | |
| if (!highlight) | |
| return; | |
| lineRow.removeChildren(); | |
| var line = this._textModel.line(lineNumber); | |
| if (!line) | |
| lineRow.appendChild(document.createElement("br")); | |
| var plainTextStart = -1; | |
| for (var j = 0; j < line.length;) { | |
| if (j > 1000) { | |
| if (plainTextStart === -1) | |
| plainTextStart = j; | |
| break; | |
| } | |
| var attribute = highlight[j]; | |
| if (!attribute || !attribute.tokenType) { | |
| if (plainTextStart === -1) | |
| plainTextStart = j; | |
| j++; | |
| } else { | |
| if (plainTextStart !== -1) { | |
| this._appendTextNode(lineRow, line.substring(plainTextStart, j)); | |
| plainTextStart = -1; | |
| --this._paintLinesOperationsCredit; | |
| } | |
| this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType); | |
| j += attribute.length; | |
| --this._paintLinesOperationsCredit; | |
| } | |
| } | |
| if (plainTextStart !== -1) { | |
| this._appendTextNode(lineRow, line.substring(plainTextStart, line.length)); | |
| --this._paintLinesOperationsCredit; | |
| } | |
| if (lineRow.decorationsElement) | |
| lineRow.appendChild(lineRow.decorationsElement); | |
| } finally { | |
| if (this._rangeToMark && this._rangeToMark.startLine === lineNumber) | |
| this._markedRangeElement = WebInspector.highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn); | |
| this.endDomUpdates(); | |
| } | |
| }, | |
| _releaseLinesHighlight: function(lineRow) | |
| { | |
| if (!lineRow) | |
| return; | |
| if ("spans" in lineRow) { | |
| var spans = lineRow.spans; | |
| for (var j = 0; j < spans.length; ++j) | |
| this._cachedSpans.push(spans[j]); | |
| delete lineRow.spans; | |
| } | |
| if ("textNodes" in lineRow) { | |
| var textNodes = lineRow.textNodes; | |
| for (var j = 0; j < textNodes.length; ++j) | |
| this._cachedTextNodes.push(textNodes[j]); | |
| delete lineRow.textNodes; | |
| } | |
| this._cachedRows.push(lineRow); | |
| }, | |
| _getSelection: function() | |
| { | |
| var selection = window.getSelection(); | |
| if (!selection.rangeCount) | |
| return null; | |
| if (!this._container.isAncestor(selection.anchorNode) || !this._container.isAncestor(selection.focusNode)) | |
| return null; | |
| var start = this._selectionToPosition(selection.anchorNode, selection.anchorOffset); | |
| var end = selection.isCollapsed ? start : this._selectionToPosition(selection.focusNode, selection.focusOffset); | |
| return new WebInspector.TextRange(start.line, start.column, end.line, end.column); | |
| }, | |
| _restoreSelection: function(range, scrollIntoView) | |
| { | |
| if (!range) | |
| return; | |
| var start = this._positionToSelection(range.startLine, range.startColumn); | |
| var end = range.isEmpty() ? start : this._positionToSelection(range.endLine, range.endColumn); | |
| window.getSelection().setBaseAndExtent(start.container, start.offset, end.container, end.offset); | |
| if (scrollIntoView) { | |
| for (var node = end.container; node; node = node.parentElement) { | |
| if (node.scrollIntoViewIfNeeded) { | |
| node.scrollIntoViewIfNeeded(); | |
| break; | |
| } | |
| } | |
| } | |
| }, | |
| _selectionToPosition: function(container, offset) | |
| { | |
| if (container === this._container && offset === 0) | |
| return { line: 0, column: 0 }; | |
| if (container === this._container && offset === 1) | |
| return { line: this._textModel.linesCount - 1, column: this._textModel.lineLength(this._textModel.linesCount - 1) }; | |
| var lineRow = this._enclosingLineRowOrSelf(container); | |
| var lineNumber = lineRow.lineNumber; | |
| if (container === lineRow && offset === 0) | |
| return { line: lineNumber, column: 0 }; | |
| var column = 0; | |
| var node = lineRow.nodeType === Node.TEXT_NODE ? lineRow : lineRow.traverseNextTextNode(lineRow); | |
| while (node && node !== container) { | |
| var text = node.textContent; | |
| for (var i = 0; i < text.length; ++i) { | |
| if (text.charAt(i) === "\n") { | |
| lineNumber++; | |
| column = 0; | |
| } else | |
| column++; | |
| } | |
| node = node.traverseNextTextNode(lineRow); | |
| } | |
| if (node === container && offset) { | |
| var text = node.textContent; | |
| for (var i = 0; i < offset; ++i) { | |
| if (text.charAt(i) === "\n") { | |
| lineNumber++; | |
| column = 0; | |
| } else | |
| column++; | |
| } | |
| } | |
| return { line: lineNumber, column: column }; | |
| }, | |
| _positionToSelection: function(line, column) | |
| { | |
| var chunk = this.chunkForLine(line); | |
| var lineRow = chunk.linesCount === 1 ? chunk.element : chunk.getExpandedLineRow(line); | |
| if (lineRow) | |
| var rangeBoundary = lineRow.rangeBoundaryForOffset(column); | |
| else { | |
| var offset = column; | |
| for (var i = chunk.startLine; i < line; ++i) | |
| offset += this._textModel.lineLength(i) + 1; | |
| lineRow = chunk.element; | |
| if (lineRow.firstChild) | |
| var rangeBoundary = { container: lineRow.firstChild, offset: offset }; | |
| else | |
| var rangeBoundary = { container: lineRow, offset: 0 }; | |
| } | |
| return rangeBoundary; | |
| }, | |
| _enclosingLineRowOrSelf: function(element) | |
| { | |
| var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content"); | |
| if (lineRow) | |
| return lineRow; | |
| for (lineRow = element; lineRow; lineRow = lineRow.parentElement) { | |
| if (lineRow.parentElement === this._container) | |
| return lineRow; | |
| } | |
| return null; | |
| }, | |
| _appendSpan: function(element, content, className) | |
| { | |
| if (className === "html-resource-link" || className === "html-external-link") { | |
| element.appendChild(this._createLink(content, className === "html-external-link")); | |
| return; | |
| } | |
| var span = this._cachedSpans.pop() || document.createElement("span"); | |
| span.className = "webkit-" + className; | |
| span.textContent = content; | |
| element.appendChild(span); | |
| if (!("spans" in element)) | |
| element.spans = []; | |
| element.spans.push(span); | |
| }, | |
| _appendTextNode: function(element, text) | |
| { | |
| var textNode = this._cachedTextNodes.pop(); | |
| if (textNode) | |
| textNode.nodeValue = text; | |
| else | |
| textNode = document.createTextNode(text); | |
| element.appendChild(textNode); | |
| if (!("textNodes" in element)) | |
| element.textNodes = []; | |
| element.textNodes.push(textNode); | |
| }, | |
| _createLink: function(content, isExternal) | |
| { | |
| var quote = content.charAt(0); | |
| if (content.length > 1 && (quote === "\"" || quote === "'")) | |
| content = content.substring(1, content.length - 1); | |
| else | |
| quote = null; | |
| var span = document.createElement("span"); | |
| span.className = "webkit-html-attribute-value"; | |
| if (quote) | |
| span.appendChild(document.createTextNode(quote)); | |
| span.appendChild(this._delegate.createLink(content, isExternal)); | |
| if (quote) | |
| span.appendChild(document.createTextNode(quote)); | |
| return span; | |
| }, | |
| _handleDOMUpdates: function(e) | |
| { | |
| if (this._domUpdateCoalescingLevel) | |
| return; | |
| var target = e.target; | |
| if (target === this._container) | |
| return; | |
| var lineRow = this._enclosingLineRowOrSelf(target); | |
| if (!lineRow) | |
| return; | |
| if (lineRow.decorationsElement && lineRow.decorationsElement.isSelfOrAncestor(target)) { | |
| if (this._syncDecorationsForLineListener) | |
| this._syncDecorationsForLineListener(lineRow.lineNumber); | |
| return; | |
| } | |
| if (this._readOnly) | |
| return; | |
| if (target === lineRow && e.type === "DOMNodeInserted") { | |
| delete lineRow.lineNumber; | |
| } | |
| var startLine = 0; | |
| for (var row = lineRow; row; row = row.previousSibling) { | |
| if (typeof row.lineNumber === "number") { | |
| startLine = row.lineNumber; | |
| break; | |
| } | |
| } | |
| var endLine = startLine + 1; | |
| for (var row = lineRow.nextSibling; row; row = row.nextSibling) { | |
| if (typeof row.lineNumber === "number" && row.lineNumber > startLine) { | |
| endLine = row.lineNumber; | |
| break; | |
| } | |
| } | |
| if (this._dirtyLines) { | |
| this._dirtyLines.start = Math.min(this._dirtyLines.start, startLine); | |
| this._dirtyLines.end = Math.max(this._dirtyLines.end, endLine); | |
| } else { | |
| this._dirtyLines = { start: startLine, end: endLine }; | |
| setTimeout(this._applyDomUpdates.bind(this), 0); | |
| this.markAndRevealRange(null); | |
| } | |
| }, | |
| _applyDomUpdates: function() | |
| { | |
| if (!this._dirtyLines) | |
| return; | |
| if (this._readOnly) { | |
| delete this._dirtyLines; | |
| return; | |
| } | |
| var dirtyLines = this._dirtyLines; | |
| var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start); | |
| var startLine = this._textChunks[firstChunkNumber].startLine; | |
| var endLine = this._textModel.linesCount; | |
| var firstLineRow; | |
| if (firstChunkNumber) { | |
| var chunk = this._textChunks[firstChunkNumber - 1]; | |
| firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element; | |
| firstLineRow = firstLineRow.nextSibling; | |
| } else | |
| firstLineRow = this._container.firstChild; | |
| var lines = []; | |
| for (var lineRow = firstLineRow; lineRow; lineRow = lineRow.nextSibling) { | |
| if (typeof lineRow.lineNumber === "number" && lineRow.lineNumber >= dirtyLines.end) { | |
| endLine = lineRow.lineNumber; | |
| break; | |
| } | |
| lineRow.lineNumber = startLine + lines.length; | |
| this._collectLinesFromDiv(lines, lineRow); | |
| } | |
| var startOffset = 0; | |
| while (startLine < dirtyLines.start && startOffset < lines.length) { | |
| if (this._textModel.line(startLine) !== lines[startOffset]) | |
| break; | |
| ++startOffset; | |
| ++startLine; | |
| } | |
| var endOffset = lines.length; | |
| while (endLine > dirtyLines.end && endOffset > startOffset) { | |
| if (this._textModel.line(endLine - 1) !== lines[endOffset - 1]) | |
| break; | |
| --endOffset; | |
| --endLine; | |
| } | |
| lines = lines.slice(startOffset, endOffset); | |
| var startColumn = 0; | |
| var endColumn = this._textModel.lineLength(endLine - 1); | |
| if (lines.length > 0) { | |
| var line1 = this._textModel.line(startLine); | |
| var line2 = lines[0]; | |
| while (line1[startColumn] && line1[startColumn] === line2[startColumn]) | |
| ++startColumn; | |
| lines[0] = line2.substring(startColumn); | |
| line1 = this._textModel.line(endLine - 1); | |
| line2 = lines[lines.length - 1]; | |
| for (var i = 0; i < endColumn && i < line2.length; ++i) { | |
| if (startLine === endLine - 1 && endColumn - i <= startColumn) | |
| break; | |
| if (line1[endColumn - i - 1] !== line2[line2.length - i - 1]) | |
| break; | |
| } | |
| if (i) { | |
| endColumn -= i; | |
| lines[lines.length - 1] = line2.substring(0, line2.length - i); | |
| } | |
| } | |
| var selection = this._getSelection(); | |
| if (lines.length === 0 && endLine < this._textModel.linesCount) | |
| var oldRange = new WebInspector.TextRange(startLine, 0, endLine, 0); | |
| else if (lines.length === 0 && startLine > 0) | |
| var oldRange = new WebInspector.TextRange(startLine - 1, this._textModel.lineLength(startLine - 1), endLine - 1, this._textModel.lineLength(endLine - 1)); | |
| else | |
| var oldRange = new WebInspector.TextRange(startLine, startColumn, endLine - 1, endColumn); | |
| var newContent = lines.join("\n"); | |
| if (this._textModel.copyRange(oldRange) === newContent) { | |
| delete this._dirtyLines; | |
| return; | |
| } | |
| if (lines.length === 1 && lines[0] === "}" && oldRange.isEmpty() && selection.isEmpty() && !this._textModel.line(oldRange.endLine).trim()) | |
| this._unindentAfterBlock(oldRange, selection); | |
| this._enterTextChangeMode(); | |
| delete this._dirtyLines; | |
| var newRange = this._editRange(oldRange, newContent); | |
| this._paintScheduledLines(true); | |
| this._restoreSelection(selection); | |
| this._exitTextChangeMode(oldRange, newRange); | |
| }, | |
| _unindentAfterBlock: function(oldRange, selection) | |
| { | |
| var nestingLevel = 1; | |
| for (var i = oldRange.endLine; i >= 0; --i) { | |
| var attribute = this._textModel.getAttribute(i, "highlight"); | |
| if (!attribute) | |
| continue; | |
| var columnNumbers = Object.keys(attribute).reverse(); | |
| for (var j = 0; j < columnNumbers.length; ++j) { | |
| var column = columnNumbers[j]; | |
| if (attribute[column].tokenType === "block-start") { | |
| if (!(--nestingLevel)) { | |
| var lineContent = this._textModel.line(i); | |
| var blockOffset = lineContent.length - lineContent.trimLeft().length; | |
| if (blockOffset < oldRange.startColumn) { | |
| oldRange.startColumn = blockOffset; | |
| selection.startColumn = blockOffset + 1; | |
| selection.endColumn = blockOffset + 1; | |
| } | |
| return; | |
| } | |
| } | |
| if (attribute[column].tokenType === "block-end") | |
| ++nestingLevel; | |
| } | |
| } | |
| }, | |
| textChanged: function(oldRange, newRange) | |
| { | |
| this.beginDomUpdates(); | |
| this._removeDecorationsInRange(oldRange); | |
| this._updateChunksForRanges(oldRange, newRange); | |
| this._updateHighlightsForRange(newRange); | |
| this.endDomUpdates(); | |
| }, | |
| _editRange: function(range, text) | |
| { | |
| if (this._lastEditedRange && (!text || text.indexOf("\n") !== -1 || this._lastEditedRange.endLine !== range.startLine || this._lastEditedRange.endColumn !== range.startColumn)) | |
| this._textModel.markUndoableState(); | |
| var newRange = this._textModel.editRange(range, text); | |
| this._lastEditedRange = newRange; | |
| return newRange; | |
| }, | |
| _removeDecorationsInRange: function(range) | |
| { | |
| for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) { | |
| var chunk = this._textChunks[i]; | |
| if (chunk.startLine > range.endLine) | |
| break; | |
| chunk.removeAllDecorations(); | |
| } | |
| }, | |
| _updateChunksForRanges: function(oldRange, newRange) | |
| { | |
| var firstChunkNumber = this._chunkNumberForLine(oldRange.startLine); | |
| var lastChunkNumber = firstChunkNumber; | |
| while (lastChunkNumber + 1 < this._textChunks.length) { | |
| if (this._textChunks[lastChunkNumber + 1].startLine > oldRange.endLine) | |
| break; | |
| ++lastChunkNumber; | |
| } | |
| var startLine = this._textChunks[firstChunkNumber].startLine; | |
| var linesCount = this._textChunks[lastChunkNumber].startLine + this._textChunks[lastChunkNumber].linesCount - startLine; | |
| var linesDiff = newRange.linesCount - oldRange.linesCount; | |
| linesCount += linesDiff; | |
| if (linesDiff) { | |
| for (var chunkNumber = lastChunkNumber + 1; chunkNumber < this._textChunks.length; ++chunkNumber) | |
| this._textChunks[chunkNumber].startLine += linesDiff; | |
| } | |
| var firstLineRow; | |
| if (firstChunkNumber) { | |
| var chunk = this._textChunks[firstChunkNumber - 1]; | |
| firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element; | |
| firstLineRow = firstLineRow.nextSibling; | |
| } else | |
| firstLineRow = this._container.firstChild; | |
| for (var chunkNumber = firstChunkNumber; chunkNumber <= lastChunkNumber; ++chunkNumber) { | |
| var chunk = this._textChunks[chunkNumber]; | |
| if (chunk.startLine + chunk.linesCount > this._textModel.linesCount) | |
| break; | |
| var lineNumber = chunk.startLine; | |
| for (var lineRow = firstLineRow; lineRow && lineNumber < chunk.startLine + chunk.linesCount; lineRow = lineRow.nextSibling) { | |
| if (lineRow.lineNumber !== lineNumber || lineRow !== chunk.getExpandedLineRow(lineNumber) || lineRow.textContent !== this._textModel.line(lineNumber) || !lineRow.firstChild) | |
| break; | |
| ++lineNumber; | |
| } | |
| if (lineNumber < chunk.startLine + chunk.linesCount) | |
| break; | |
| chunk.updateCollapsedLineRow(); | |
| ++firstChunkNumber; | |
| firstLineRow = lineRow; | |
| startLine += chunk.linesCount; | |
| linesCount -= chunk.linesCount; | |
| } | |
| if (firstChunkNumber > lastChunkNumber && linesCount === 0) | |
| return; | |
| var chunk = this._textChunks[lastChunkNumber + 1]; | |
| var linesInLastChunk = linesCount % this._defaultChunkSize; | |
| if (chunk && !chunk.decorated && linesInLastChunk > 0 && linesInLastChunk + chunk.linesCount <= this._defaultChunkSize) { | |
| ++lastChunkNumber; | |
| linesCount += chunk.linesCount; | |
| } | |
| var scrollTop = this.element.scrollTop; | |
| var scrollLeft = this.element.scrollLeft; | |
| var firstUnmodifiedLineRow = null; | |
| chunk = this._textChunks[lastChunkNumber + 1]; | |
| if (chunk) | |
| firstUnmodifiedLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine) : chunk.element; | |
| while (firstLineRow && firstLineRow !== firstUnmodifiedLineRow) { | |
| var lineRow = firstLineRow; | |
| firstLineRow = firstLineRow.nextSibling; | |
| this._container.removeChild(lineRow); | |
| } | |
| for (var chunkNumber = firstChunkNumber; linesCount > 0; ++chunkNumber) { | |
| var chunkLinesCount = Math.min(this._defaultChunkSize, linesCount); | |
| var newChunk = this._createNewChunk(startLine, startLine + chunkLinesCount); | |
| this._container.insertBefore(newChunk.element, firstUnmodifiedLineRow); | |
| if (chunkNumber <= lastChunkNumber) | |
| this._textChunks[chunkNumber] = newChunk; | |
| else | |
| this._textChunks.splice(chunkNumber, 0, newChunk); | |
| startLine += chunkLinesCount; | |
| linesCount -= chunkLinesCount; | |
| } | |
| if (chunkNumber <= lastChunkNumber) | |
| this._textChunks.splice(chunkNumber, lastChunkNumber - chunkNumber + 1); | |
| this.element.scrollTop = scrollTop; | |
| this.element.scrollLeft = scrollLeft; | |
| }, | |
| _updateHighlightsForRange: function(range) | |
| { | |
| var visibleFrom = this.element.scrollTop; | |
| var visibleTo = this.element.scrollTop + this.element.clientHeight; | |
| var result = this._findVisibleChunks(visibleFrom, visibleTo); | |
| var chunk = this._textChunks[result.end - 1]; | |
| var lastVisibleLine = chunk.startLine + chunk.linesCount; | |
| lastVisibleLine = Math.max(lastVisibleLine, range.endLine + 1); | |
| lastVisibleLine = Math.min(lastVisibleLine, this._textModel.linesCount); | |
| var updated = this._highlighter.updateHighlight(range.startLine, lastVisibleLine); | |
| if (!updated) { | |
| for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) | |
| this._textChunks[i].expanded = false; | |
| } | |
| this._repaintAll(); | |
| }, | |
| _collectLinesFromDiv: function(lines, element) | |
| { | |
| var textContents = []; | |
| var node = element.nodeType === Node.TEXT_NODE ? element : element.traverseNextNode(element); | |
| while (node) { | |
| if (element.decorationsElement === node) { | |
| node = node.nextSibling; | |
| continue; | |
| } | |
| if (node.nodeName.toLowerCase() === "br") | |
| textContents.push("\n"); | |
| else if (node.nodeType === Node.TEXT_NODE) | |
| textContents.push(node.textContent); | |
| node = node.traverseNextNode(element); | |
| } | |
| var textContent = textContents.join(""); | |
| textContent = textContent.replace(/\n$/, ""); | |
| textContents = textContent.split("\n"); | |
| for (var i = 0; i < textContents.length; ++i) | |
| lines.push(textContents[i]); | |
| } | |
| } | |
| WebInspector.TextEditorMainPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype; | |
| WebInspector.TextEditorMainChunk = function(chunkedPanel, startLine, endLine) | |
| { | |
| this._chunkedPanel = chunkedPanel; | |
| this._textModel = chunkedPanel._textModel; | |
| this.element = document.createElement("div"); | |
| this.element.lineNumber = startLine; | |
| this.element.className = "webkit-line-content"; | |
| this._startLine = startLine; | |
| endLine = Math.min(this._textModel.linesCount, endLine); | |
| this.linesCount = endLine - startLine; | |
| this._expanded = false; | |
| this._readOnly = false; | |
| this.updateCollapsedLineRow(); | |
| } | |
| WebInspector.TextEditorMainChunk.prototype = { | |
| addDecoration: function(decoration) | |
| { | |
| this._chunkedPanel.beginDomUpdates(); | |
| if (typeof decoration === "string") | |
| this.element.addStyleClass(decoration); | |
| else { | |
| if (!this.element.decorationsElement) { | |
| this.element.decorationsElement = document.createElement("div"); | |
| this.element.decorationsElement.className = "webkit-line-decorations"; | |
| this.element.appendChild(this.element.decorationsElement); | |
| } | |
| this.element.decorationsElement.appendChild(decoration); | |
| } | |
| this._chunkedPanel.endDomUpdates(); | |
| }, | |
| removeDecoration: function(decoration) | |
| { | |
| this._chunkedPanel.beginDomUpdates(); | |
| if (typeof decoration === "string") | |
| this.element.removeStyleClass(decoration); | |
| else if (this.element.decorationsElement) | |
| this.element.decorationsElement.removeChild(decoration); | |
| this._chunkedPanel.endDomUpdates(); | |
| }, | |
| removeAllDecorations: function() | |
| { | |
| this._chunkedPanel.beginDomUpdates(); | |
| this.element.className = "webkit-line-content"; | |
| if (this.element.decorationsElement) { | |
| this.element.removeChild(this.element.decorationsElement); | |
| delete this.element.decorationsElement; | |
| } | |
| this._chunkedPanel.endDomUpdates(); | |
| }, | |
| get decorated() | |
| { | |
| return this.element.className !== "webkit-line-content" || !!(this.element.decorationsElement && this.element.decorationsElement.firstChild); | |
| }, | |
| get startLine() | |
| { | |
| return this._startLine; | |
| }, | |
| set startLine(startLine) | |
| { | |
| this._startLine = startLine; | |
| this.element.lineNumber = startLine; | |
| if (this._expandedLineRows) { | |
| for (var i = 0; i < this._expandedLineRows.length; ++i) | |
| this._expandedLineRows[i].lineNumber = startLine + i; | |
| } | |
| }, | |
| get expanded() | |
| { | |
| return this._expanded; | |
| }, | |
| set expanded(expanded) | |
| { | |
| if (this._expanded === expanded) | |
| return; | |
| this._expanded = expanded; | |
| if (this.linesCount === 1) { | |
| if (expanded) | |
| this._chunkedPanel._paintLine(this.element); | |
| return; | |
| } | |
| this._chunkedPanel.beginDomUpdates(); | |
| if (expanded) { | |
| this._expandedLineRows = []; | |
| var parentElement = this.element.parentElement; | |
| for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) { | |
| var lineRow = this._createRow(i); | |
| this._updateElementReadOnlyState(lineRow); | |
| parentElement.insertBefore(lineRow, this.element); | |
| this._expandedLineRows.push(lineRow); | |
| } | |
| parentElement.removeChild(this.element); | |
| this._chunkedPanel._paintLines(this.startLine, this.startLine + this.linesCount); | |
| } else { | |
| var elementInserted = false; | |
| for (var i = 0; i < this._expandedLineRows.length; ++i) { | |
| var lineRow = this._expandedLineRows[i]; | |
| var parentElement = lineRow.parentElement; | |
| if (parentElement) { | |
| if (!elementInserted) { | |
| elementInserted = true; | |
| parentElement.insertBefore(this.element, lineRow); | |
| } | |
| parentElement.removeChild(lineRow); | |
| } | |
| this._chunkedPanel._releaseLinesHighlight(lineRow); | |
| } | |
| delete this._expandedLineRows; | |
| } | |
| this._chunkedPanel.endDomUpdates(); | |
| }, | |
| set readOnly(readOnly) | |
| { | |
| if (this._readOnly === readOnly) | |
| return; | |
| this._readOnly = readOnly; | |
| this._updateElementReadOnlyState(this.element); | |
| if (this._expandedLineRows) { | |
| for (var i = 0; i < this._expandedLineRows.length; ++i) | |
| this._updateElementReadOnlyState(this._expandedLineRows[i]); | |
| } | |
| }, | |
| get readOnly() | |
| { | |
| return this._readOnly; | |
| }, | |
| _updateElementReadOnlyState: function(element) | |
| { | |
| if (this._readOnly) | |
| element.addStyleClass("text-editor-read-only"); | |
| else | |
| element.removeStyleClass("text-editor-read-only"); | |
| }, | |
| get height() | |
| { | |
| if (!this._expandedLineRows) | |
| return this._chunkedPanel._totalHeight(this.element); | |
| return this._chunkedPanel._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]); | |
| }, | |
| get offsetTop() | |
| { | |
| return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop; | |
| }, | |
| _createRow: function(lineNumber) | |
| { | |
| var lineRow = this._chunkedPanel._cachedRows.pop() || document.createElement("div"); | |
| lineRow.lineNumber = lineNumber; | |
| lineRow.className = "webkit-line-content"; | |
| lineRow.textContent = this._textModel.line(lineNumber); | |
| if (!lineRow.textContent) | |
| lineRow.appendChild(document.createElement("br")); | |
| return lineRow; | |
| }, | |
| getExpandedLineRow: function(lineNumber) | |
| { | |
| if (!this._expanded || lineNumber < this.startLine || lineNumber >= this.startLine + this.linesCount) | |
| return null; | |
| if (!this._expandedLineRows) | |
| return this.element; | |
| return this._expandedLineRows[lineNumber - this.startLine]; | |
| }, | |
| updateCollapsedLineRow: function() | |
| { | |
| if (this.linesCount === 1 && this._expanded) | |
| return; | |
| var lines = []; | |
| for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) | |
| lines.push(this._textModel.line(i)); | |
| this.element.removeChildren(); | |
| this.element.textContent = lines.join("\n"); | |
| if (!lines[lines.length - 1]) | |
| this.element.appendChild(document.createElement("br")); | |
| } | |
| } | |
| WebInspector.SourceFrame = function(contentProvider) | |
| { | |
| WebInspector.View.call(this); | |
| this.element.addStyleClass("script-view"); | |
| this._url = contentProvider.contentURL(); | |
| this._contentProvider = contentProvider; | |
| var textEditorDelegate = new WebInspector.TextEditorDelegateForSourceFrame(this); | |
| if (WebInspector.experimentsSettings.codemirror.isEnabled()) { | |
| importScript("CodeMirrorTextEditor.js"); | |
| this._textEditor = new WebInspector.CodeMirrorTextEditor(this._url, textEditorDelegate); | |
| } else | |
| this._textEditor = new WebInspector.DefaultTextEditor(this._url, textEditorDelegate); | |
| this._currentSearchResultIndex = -1; | |
| this._searchResults = []; | |
| this._messages = []; | |
| this._rowMessages = {}; | |
| this._messageBubbles = {}; | |
| this._textEditor.setReadOnly(!this.canEditSource()); | |
| this._shortcuts = {}; | |
| this._shortcuts[WebInspector.KeyboardShortcut.makeKey("s", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)] = this._commitEditing.bind(this); | |
| this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); | |
| } | |
| WebInspector.SourceFrame.createSearchRegex = function(query, modifiers) | |
| { | |
| var regex; | |
| modifiers = modifiers || ""; | |
| try { | |
| if (/^\/.*\/$/.test(query)) | |
| regex = new RegExp(query.substring(1, query.length - 1), modifiers); | |
| } catch (e) { | |
| } | |
| if (!regex) | |
| regex = createPlainTextSearchRegex(query, "i" + modifiers); | |
| return regex; | |
| } | |
| WebInspector.SourceFrame.Events = { | |
| ScrollChanged: "ScrollChanged", | |
| SelectionChanged: "SelectionChanged" | |
| } | |
| WebInspector.SourceFrame.prototype = { | |
| wasShown: function() | |
| { | |
| this._ensureContentLoaded(); | |
| this._textEditor.show(this.element); | |
| this._wasShownOrLoaded(); | |
| }, | |
| willHide: function() | |
| { | |
| WebInspector.View.prototype.willHide.call(this); | |
| this._clearLineHighlight(); | |
| this._clearLineToReveal(); | |
| }, | |
| statusBarItems: function() | |
| { | |
| return []; | |
| }, | |
| defaultFocusedElement: function() | |
| { | |
| return this._textEditor.defaultFocusedElement(); | |
| }, | |
| get loaded() | |
| { | |
| return this._loaded; | |
| }, | |
| hasContent: function() | |
| { | |
| return true; | |
| }, | |
| get textEditor() | |
| { | |
| return this._textEditor; | |
| }, | |
| _ensureContentLoaded: function() | |
| { | |
| if (!this._contentRequested) { | |
| this._contentRequested = true; | |
| this._contentProvider.requestContent(this.setContent.bind(this)); | |
| } | |
| }, | |
| addMessage: function(msg) | |
| { | |
| this._messages.push(msg); | |
| if (this.loaded) | |
| this.addMessageToSource(msg.line - 1, msg); | |
| }, | |
| clearMessages: function() | |
| { | |
| for (var line in this._messageBubbles) { | |
| var bubble = this._messageBubbles[line]; | |
| bubble.parentNode.removeChild(bubble); | |
| } | |
| this._messages = []; | |
| this._rowMessages = {}; | |
| this._messageBubbles = {}; | |
| this._textEditor.doResize(); | |
| }, | |
| canHighlightLine: function(line) | |
| { | |
| return true; | |
| }, | |
| highlightLine: function(line) | |
| { | |
| this._clearLineToReveal(); | |
| this._clearLineToScrollTo(); | |
| this._lineToHighlight = line; | |
| this._innerHighlightLineIfNeeded(); | |
| this._textEditor.setSelection(WebInspector.TextRange.createFromLocation(line, 0)); | |
| }, | |
| _innerHighlightLineIfNeeded: function() | |
| { | |
| if (typeof this._lineToHighlight === "number") { | |
| if (this.loaded && this._textEditor.isShowing()) { | |
| this._textEditor.highlightLine(this._lineToHighlight); | |
| delete this._lineToHighlight | |
| } | |
| } | |
| }, | |
| _clearLineHighlight: function() | |
| { | |
| this._textEditor.clearLineHighlight(); | |
| delete this._lineToHighlight; | |
| }, | |
| revealLine: function(line) | |
| { | |
| this._clearLineHighlight(); | |
| this._clearLineToScrollTo(); | |
| this._lineToReveal = line; | |
| this._innerRevealLineIfNeeded(); | |
| }, | |
| _innerRevealLineIfNeeded: function() | |
| { | |
| if (typeof this._lineToReveal === "number") { | |
| if (this.loaded && this._textEditor.isShowing()) { | |
| this._textEditor.revealLine(this._lineToReveal); | |
| delete this._lineToReveal | |
| } | |
| } | |
| }, | |
| _clearLineToReveal: function() | |
| { | |
| delete this._lineToReveal; | |
| }, | |
| scrollToLine: function(line) | |
| { | |
| this._clearLineHighlight(); | |
| this._clearLineToReveal(); | |
| this._lineToScrollTo = line; | |
| this._innerScrollToLineIfNeeded(); | |
| }, | |
| _innerScrollToLineIfNeeded: function() | |
| { | |
| if (typeof this._lineToScrollTo === "number") { | |
| if (this.loaded && this._textEditor.isShowing()) { | |
| this._textEditor.scrollToLine(this._lineToScrollTo); | |
| delete this._lineToScrollTo | |
| } | |
| } | |
| }, | |
| _clearLineToScrollTo: function() | |
| { | |
| delete this._lineToScrollTo; | |
| }, | |
| setSelection: function(textRange) | |
| { | |
| this._selectionToSet = textRange; | |
| this._innerSetSelectionIfNeeded(); | |
| }, | |
| _innerSetSelectionIfNeeded: function() | |
| { | |
| if (this._selectionToSet && this.loaded && this._textEditor.isShowing()) { | |
| this._textEditor.setSelection(this._selectionToSet); | |
| delete this._selectionToSet; | |
| } | |
| }, | |
| _wasShownOrLoaded: function() | |
| { | |
| this._innerHighlightLineIfNeeded(); | |
| this._innerRevealLineIfNeeded(); | |
| this._innerScrollToLineIfNeeded(); | |
| this._innerSetSelectionIfNeeded(); | |
| }, | |
| onTextChanged: function(oldRange, newRange) | |
| { | |
| if (!this._isReplacing) | |
| WebInspector.searchController.cancelSearch(); | |
| this.clearMessages(); | |
| }, | |
| setContent: function(content, contentEncoded, mimeType) | |
| { | |
| this._textEditor.mimeType = mimeType; | |
| this._loaded = true; | |
| this._textEditor.setText(content || ""); | |
| this._textEditor.beginUpdates(); | |
| this._setTextEditorDecorations(); | |
| this._wasShownOrLoaded(); | |
| if (this._delayedFindSearchMatches) { | |
| this._delayedFindSearchMatches(); | |
| delete this._delayedFindSearchMatches; | |
| } | |
| this.onTextEditorContentLoaded(); | |
| this._textEditor.endUpdates(); | |
| }, | |
| onTextEditorContentLoaded: function() {}, | |
| _setTextEditorDecorations: function() | |
| { | |
| this._rowMessages = {}; | |
| this._messageBubbles = {}; | |
| this._textEditor.beginUpdates(); | |
| this._addExistingMessagesToSource(); | |
| this._textEditor.doResize(); | |
| this._textEditor.endUpdates(); | |
| }, | |
| performSearch: function(query, callback) | |
| { | |
| this.searchCanceled(); | |
| function doFindSearchMatches(query) | |
| { | |
| this._currentSearchResultIndex = -1; | |
| this._searchResults = []; | |
| var regex = WebInspector.SourceFrame.createSearchRegex(query); | |
| this._searchResults = this._collectRegexMatches(regex); | |
| var shiftToIndex = 0; | |
| var selection = this._textEditor.lastSelection(); | |
| for (var i = 0; selection && i < this._searchResults.length; ++i) { | |
| if (this._searchResults[i].compareTo(selection) >= 0) { | |
| shiftToIndex = i; | |
| break; | |
| } | |
| } | |
| if (shiftToIndex) | |
| this._searchResults = this._searchResults.rotate(shiftToIndex); | |
| callback(this, this._searchResults.length); | |
| } | |
| if (this.loaded) | |
| doFindSearchMatches.call(this, query); | |
| else | |
| this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query); | |
| this._ensureContentLoaded(); | |
| }, | |
| searchCanceled: function() | |
| { | |
| delete this._delayedFindSearchMatches; | |
| if (!this.loaded) | |
| return; | |
| this._currentSearchResultIndex = -1; | |
| this._searchResults = []; | |
| this._textEditor.markAndRevealRange(null); | |
| }, | |
| hasSearchResults: function() | |
| { | |
| return this._searchResults.length > 0; | |
| }, | |
| jumpToFirstSearchResult: function() | |
| { | |
| this.jumpToSearchResult(0); | |
| }, | |
| jumpToLastSearchResult: function() | |
| { | |
| this.jumpToSearchResult(this._searchResults.length - 1); | |
| }, | |
| jumpToNextSearchResult: function() | |
| { | |
| this.jumpToSearchResult(this._currentSearchResultIndex + 1); | |
| }, | |
| jumpToPreviousSearchResult: function() | |
| { | |
| this.jumpToSearchResult(this._currentSearchResultIndex - 1); | |
| }, | |
| showingFirstSearchResult: function() | |
| { | |
| return this._searchResults.length && this._currentSearchResultIndex === 0; | |
| }, | |
| showingLastSearchResult: function() | |
| { | |
| return this._searchResults.length && this._currentSearchResultIndex === (this._searchResults.length - 1); | |
| }, | |
| get currentSearchResultIndex() | |
| { | |
| return this._currentSearchResultIndex; | |
| }, | |
| jumpToSearchResult: function(index) | |
| { | |
| if (!this.loaded || !this._searchResults.length) | |
| return; | |
| this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length; | |
| this._textEditor.markAndRevealRange(this._searchResults[this._currentSearchResultIndex]); | |
| }, | |
| replaceSearchMatchWith: function(text) | |
| { | |
| var range = this._searchResults[this._currentSearchResultIndex]; | |
| if (!range) | |
| return; | |
| this._textEditor.markAndRevealRange(null); | |
| this._isReplacing = true; | |
| var newRange = this._textEditor.editRange(range, text); | |
| delete this._isReplacing; | |
| this._textEditor.setSelection(newRange.collapseToEnd()); | |
| }, | |
| replaceAllWith: function(query, replacement) | |
| { | |
| this._textEditor.markAndRevealRange(null); | |
| var text = this._textEditor.text(); | |
| var range = this._textEditor.range(); | |
| text = text.replace(WebInspector.SourceFrame.createSearchRegex(query, "g"), replacement); | |
| this._isReplacing = true; | |
| this._textEditor.editRange(range, text); | |
| delete this._isReplacing; | |
| }, | |
| _collectRegexMatches: function(regexObject) | |
| { | |
| var ranges = []; | |
| for (var i = 0; i < this._textEditor.linesCount; ++i) { | |
| var line = this._textEditor.line(i); | |
| var offset = 0; | |
| do { | |
| var match = regexObject.exec(line); | |
| if (match) { | |
| if (match[0].length) | |
| ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length)); | |
| offset += match.index + 1; | |
| line = line.substring(match.index + 1); | |
| } | |
| } while (match && line); | |
| } | |
| return ranges; | |
| }, | |
| _addExistingMessagesToSource: function() | |
| { | |
| var length = this._messages.length; | |
| for (var i = 0; i < length; ++i) | |
| this.addMessageToSource(this._messages[i].line - 1, this._messages[i]); | |
| }, | |
| addMessageToSource: function(lineNumber, msg) | |
| { | |
| if (lineNumber >= this._textEditor.linesCount) | |
| lineNumber = this._textEditor.linesCount - 1; | |
| if (lineNumber < 0) | |
| lineNumber = 0; | |
| var messageBubbleElement = this._messageBubbles[lineNumber]; | |
| if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) { | |
| messageBubbleElement = document.createElement("div"); | |
| messageBubbleElement.className = "webkit-html-message-bubble"; | |
| this._messageBubbles[lineNumber] = messageBubbleElement; | |
| this._textEditor.addDecoration(lineNumber, messageBubbleElement); | |
| } | |
| var rowMessages = this._rowMessages[lineNumber]; | |
| if (!rowMessages) { | |
| rowMessages = []; | |
| this._rowMessages[lineNumber] = rowMessages; | |
| } | |
| for (var i = 0; i < rowMessages.length; ++i) { | |
| if (rowMessages[i].consoleMessage.isEqual(msg)) { | |
| rowMessages[i].repeatCount = msg.totalRepeatCount; | |
| this._updateMessageRepeatCount(rowMessages[i]); | |
| return; | |
| } | |
| } | |
| var rowMessage = { consoleMessage: msg }; | |
| rowMessages.push(rowMessage); | |
| var imageURL; | |
| switch (msg.level) { | |
| case WebInspector.ConsoleMessage.MessageLevel.Error: | |
| messageBubbleElement.addStyleClass("webkit-html-error-message"); | |
| imageURL = "Images/errorIcon.png"; | |
| break; | |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: | |
| messageBubbleElement.addStyleClass("webkit-html-warning-message"); | |
| imageURL = "Images/warningIcon.png"; | |
| break; | |
| } | |
| var messageLineElement = document.createElement("div"); | |
| messageLineElement.className = "webkit-html-message-line"; | |
| messageBubbleElement.appendChild(messageLineElement); | |
| var image = document.createElement("img"); | |
| image.src = imageURL; | |
| image.className = "webkit-html-message-icon"; | |
| messageLineElement.appendChild(image); | |
| messageLineElement.appendChild(document.createTextNode(msg.message)); | |
| rowMessage.element = messageLineElement; | |
| rowMessage.repeatCount = msg.totalRepeatCount; | |
| this._updateMessageRepeatCount(rowMessage); | |
| }, | |
| _updateMessageRepeatCount: function(rowMessage) | |
| { | |
| if (rowMessage.repeatCount < 2) | |
| return; | |
| if (!rowMessage.repeatCountElement) { | |
| var repeatCountElement = document.createElement("span"); | |
| rowMessage.element.appendChild(repeatCountElement); | |
| rowMessage.repeatCountElement = repeatCountElement; | |
| } | |
| rowMessage.repeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", rowMessage.repeatCount); | |
| }, | |
| removeMessageFromSource: function(lineNumber, msg) | |
| { | |
| if (lineNumber >= this._textEditor.linesCount) | |
| lineNumber = this._textEditor.linesCount - 1; | |
| if (lineNumber < 0) | |
| lineNumber = 0; | |
| var rowMessages = this._rowMessages[lineNumber]; | |
| for (var i = 0; rowMessages && i < rowMessages.length; ++i) { | |
| var rowMessage = rowMessages[i]; | |
| if (rowMessage.consoleMessage !== msg) | |
| continue; | |
| var messageLineElement = rowMessage.element; | |
| var messageBubbleElement = messageLineElement.parentElement; | |
| messageBubbleElement.removeChild(messageLineElement); | |
| rowMessages.remove(rowMessage); | |
| if (!rowMessages.length) | |
| delete this._rowMessages[lineNumber]; | |
| if (!messageBubbleElement.childElementCount) { | |
| this._textEditor.removeDecoration(lineNumber, messageBubbleElement); | |
| delete this._messageBubbles[lineNumber]; | |
| } | |
| break; | |
| } | |
| }, | |
| populateLineGutterContextMenu: function(contextMenu, lineNumber) | |
| { | |
| }, | |
| populateTextAreaContextMenu: function(contextMenu, lineNumber) | |
| { | |
| }, | |
| inheritScrollPositions: function(sourceFrame) | |
| { | |
| this._textEditor.inheritScrollPositions(sourceFrame._textEditor); | |
| }, | |
| canEditSource: function() | |
| { | |
| return false; | |
| }, | |
| commitEditing: function(text) | |
| { | |
| }, | |
| selectionChanged: function(textRange) | |
| { | |
| this.dispatchEventToListeners(WebInspector.SourceFrame.Events.SelectionChanged, textRange); | |
| }, | |
| scrollChanged: function(lineNumber) | |
| { | |
| this.dispatchEventToListeners(WebInspector.SourceFrame.Events.ScrollChanged, lineNumber); | |
| }, | |
| _handleKeyDown: function(e) | |
| { | |
| var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e); | |
| var handler = this._shortcuts[shortcutKey]; | |
| if (handler && handler()) | |
| e.consume(true); | |
| }, | |
| _commitEditing: function() | |
| { | |
| if (this._textEditor.readOnly()) | |
| return false; | |
| var content = this._textEditor.text(); | |
| this.commitEditing(content); | |
| if (this._url && WebInspector.fileManager.isURLSaved(this._url)) | |
| WebInspector.fileManager.save(this._url, content, false); | |
| return true; | |
| } | |
| } | |
| WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.TextEditorDelegateForSourceFrame = function(sourceFrame) | |
| { | |
| this._sourceFrame = sourceFrame; | |
| } | |
| WebInspector.TextEditorDelegateForSourceFrame.prototype = { | |
| onTextChanged: function(oldRange, newRange) | |
| { | |
| this._sourceFrame.onTextChanged(oldRange, newRange); | |
| }, | |
| selectionChanged: function(textRange) | |
| { | |
| this._sourceFrame.selectionChanged(textRange); | |
| }, | |
| scrollChanged: function(lineNumber) | |
| { | |
| this._sourceFrame.scrollChanged(lineNumber); | |
| }, | |
| populateLineGutterContextMenu: function(contextMenu, lineNumber) | |
| { | |
| this._sourceFrame.populateLineGutterContextMenu(contextMenu, lineNumber); | |
| }, | |
| populateTextAreaContextMenu: function(contextMenu, lineNumber) | |
| { | |
| this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber); | |
| }, | |
| createLink: function(hrefValue, isExternal) | |
| { | |
| var targetLocation = WebInspector.ParsedURL.completeURL(this._sourceFrame._url, hrefValue); | |
| return WebInspector.linkifyURLAsNode(targetLocation || hrefValue, hrefValue, undefined, isExternal); | |
| } | |
| } | |
| WebInspector.TextEditorDelegateForSourceFrame.prototype.__proto__ = WebInspector.TextEditorDelegate.prototype; | |
| WebInspector.ResourceView = function(resource) | |
| { | |
| WebInspector.View.call(this); | |
| this.registerRequiredCSS("resourceView.css"); | |
| this.element.addStyleClass("resource-view"); | |
| this.resource = resource; | |
| } | |
| WebInspector.ResourceView.prototype = { | |
| hasContent: function() | |
| { | |
| return false; | |
| } | |
| } | |
| WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.ResourceView.hasTextContent = function(resource) | |
| { | |
| if (resource.type.isTextType()) | |
| return true; | |
| if (resource.type === WebInspector.resourceTypes.Other) | |
| return resource.content && !resource.contentEncoded; | |
| return false; | |
| } | |
| WebInspector.ResourceView.nonSourceViewForResource = function(resource) | |
| { | |
| switch (resource.type) { | |
| case WebInspector.resourceTypes.Image: | |
| return new WebInspector.ImageView(resource); | |
| case WebInspector.resourceTypes.Font: | |
| return new WebInspector.FontView(resource); | |
| default: | |
| return new WebInspector.ResourceView(resource); | |
| } | |
| } | |
| WebInspector.ResourceSourceFrame = function(resource) | |
| { | |
| this._resource = resource; | |
| WebInspector.SourceFrame.call(this, resource); | |
| } | |
| WebInspector.ResourceSourceFrame.prototype = { | |
| get resource() | |
| { | |
| return this._resource; | |
| }, | |
| populateTextAreaContextMenu: function(contextMenu, lineNumber) | |
| { | |
| contextMenu.appendApplicableItems(this._resource); | |
| if (this._resource.request) | |
| contextMenu.appendApplicableItems(this._resource.request); | |
| } | |
| } | |
| WebInspector.ResourceSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype; | |
| WebInspector.FontView = function(resource) | |
| { | |
| WebInspector.ResourceView.call(this, resource); | |
| this.element.addStyleClass("font"); | |
| } | |
| WebInspector.FontView._fontPreviewLines = [ "ABCDEFGHIJKLM", "NOPQRSTUVWXYZ", "abcdefghijklm", "nopqrstuvwxyz", "1234567890" ]; | |
| WebInspector.FontView._fontId = 0; | |
| WebInspector.FontView._measureFontSize = 50; | |
| WebInspector.FontView.prototype = { | |
| hasContent: function() | |
| { | |
| return true; | |
| }, | |
| _createContentIfNeeded: function() | |
| { | |
| if (this.fontPreviewElement) | |
| return; | |
| var uniqueFontName = "WebInspectorFontPreview" + (++WebInspector.FontView._fontId); | |
| this.fontStyleElement = document.createElement("style"); | |
| this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }"; | |
| document.head.appendChild(this.fontStyleElement); | |
| var fontPreview = document.createElement("div"); | |
| for (var i = 0; i < WebInspector.FontView._fontPreviewLines.length; ++i) { | |
| if (i > 0) | |
| fontPreview.appendChild(document.createElement("br")); | |
| fontPreview.appendChild(document.createTextNode(WebInspector.FontView._fontPreviewLines[i])); | |
| } | |
| this.fontPreviewElement = fontPreview.cloneNode(true); | |
| this.fontPreviewElement.style.setProperty("font-family", uniqueFontName); | |
| this.fontPreviewElement.style.setProperty("visibility", "hidden"); | |
| this._dummyElement = fontPreview; | |
| this._dummyElement.style.visibility = "hidden"; | |
| this._dummyElement.style.zIndex = "-1"; | |
| this._dummyElement.style.display = "inline"; | |
| this._dummyElement.style.position = "absolute"; | |
| this._dummyElement.style.setProperty("font-family", uniqueFontName); | |
| this._dummyElement.style.setProperty("font-size", WebInspector.FontView._measureFontSize + "px"); | |
| this.element.appendChild(this.fontPreviewElement); | |
| }, | |
| wasShown: function() | |
| { | |
| this._createContentIfNeeded(); | |
| this.updateFontPreviewSize(); | |
| }, | |
| onResize: function() | |
| { | |
| if (this._inResize) | |
| return; | |
| this._inResize = true; | |
| try { | |
| this.updateFontPreviewSize(); | |
| } finally { | |
| delete this._inResize; | |
| } | |
| }, | |
| _measureElement: function() | |
| { | |
| this.element.appendChild(this._dummyElement); | |
| var result = { width: this._dummyElement.offsetWidth, height: this._dummyElement.offsetHeight }; | |
| this.element.removeChild(this._dummyElement); | |
| return result; | |
| }, | |
| updateFontPreviewSize: function() | |
| { | |
| if (!this.fontPreviewElement || !this.isShowing()) | |
| return; | |
| this.fontPreviewElement.style.removeProperty("visibility"); | |
| var dimension = this._measureElement(); | |
| const height = dimension.height; | |
| const width = dimension.width; | |
| const containerWidth = this.element.offsetWidth - 50; | |
| const containerHeight = this.element.offsetHeight - 30; | |
| if (!height || !width || !containerWidth || !containerHeight) { | |
| this.fontPreviewElement.style.removeProperty("font-size"); | |
| return; | |
| } | |
| var widthRatio = containerWidth / width; | |
| var heightRatio = containerHeight / height; | |
| var finalFontSize = Math.floor(WebInspector.FontView._measureFontSize * Math.min(widthRatio, heightRatio)) - 2; | |
| this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null); | |
| } | |
| } | |
| WebInspector.FontView.prototype.__proto__ = WebInspector.ResourceView.prototype; | |
| WebInspector.ImageView = function(resource) | |
| { | |
| WebInspector.ResourceView.call(this, resource); | |
| this.element.addStyleClass("image"); | |
| } | |
| WebInspector.ImageView.prototype = { | |
| hasContent: function() | |
| { | |
| return true; | |
| }, | |
| wasShown: function() | |
| { | |
| this._createContentIfNeeded(); | |
| }, | |
| _createContentIfNeeded: function() | |
| { | |
| if (this._container) | |
| return; | |
| var imageContainer = document.createElement("div"); | |
| imageContainer.className = "image"; | |
| this.element.appendChild(imageContainer); | |
| var imagePreviewElement = document.createElement("img"); | |
| imagePreviewElement.addStyleClass("resource-image-view"); | |
| imageContainer.appendChild(imagePreviewElement); | |
| imagePreviewElement.addEventListener("contextmenu", this._contextMenu.bind(this), true); | |
| this._container = document.createElement("div"); | |
| this._container.className = "info"; | |
| this.element.appendChild(this._container); | |
| var imageNameElement = document.createElement("h1"); | |
| imageNameElement.className = "title"; | |
| imageNameElement.textContent = this.resource.displayName; | |
| this._container.appendChild(imageNameElement); | |
| var infoListElement = document.createElement("dl"); | |
| infoListElement.className = "infoList"; | |
| this.resource.populateImageSource(imagePreviewElement); | |
| function onImageLoad() | |
| { | |
| var content = this.resource.content; | |
| if (content) | |
| var resourceSize = this._base64ToSize(content); | |
| else | |
| var resourceSize = this.resource.resourceSize; | |
| var imageProperties = [ | |
| { name: WebInspector.UIString("Dimensions"), value: WebInspector.UIString("%d × %d", imagePreviewElement.naturalWidth, imagePreviewElement.naturalHeight) }, | |
| { name: WebInspector.UIString("File size"), value: Number.bytesToString(resourceSize) }, | |
| { name: WebInspector.UIString("MIME type"), value: this.resource.mimeType } | |
| ]; | |
| infoListElement.removeChildren(); | |
| for (var i = 0; i < imageProperties.length; ++i) { | |
| var dt = document.createElement("dt"); | |
| dt.textContent = imageProperties[i].name; | |
| infoListElement.appendChild(dt); | |
| var dd = document.createElement("dd"); | |
| dd.textContent = imageProperties[i].value; | |
| infoListElement.appendChild(dd); | |
| } | |
| var dt = document.createElement("dt"); | |
| dt.textContent = WebInspector.UIString("URL"); | |
| infoListElement.appendChild(dt); | |
| var dd = document.createElement("dd"); | |
| var externalResource = true; | |
| dd.appendChild(WebInspector.linkifyURLAsNode(this.resource.url, undefined, undefined, externalResource)); | |
| infoListElement.appendChild(dd); | |
| this._container.appendChild(infoListElement); | |
| } | |
| imagePreviewElement.addEventListener("load", onImageLoad.bind(this), false); | |
| }, | |
| _base64ToSize: function(content) | |
| { | |
| if (!content.length) | |
| return 0; | |
| var size = (content.length || 0) * 3 / 4; | |
| if (content.length > 0 && content[content.length - 1] === "=") | |
| size--; | |
| if (content.length > 1 && content[content.length - 2] === "=") | |
| size--; | |
| return size; | |
| }, | |
| _contextMenu: function(event) | |
| { | |
| var contextMenu = new WebInspector.ContextMenu(); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy image URL" : "Copy Image URL"), this._copyImageURL.bind(this)); | |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open image in new tab" : "Open Image in New Tab"), this._openInNewTab.bind(this)); | |
| contextMenu.show(event); | |
| }, | |
| _copyImageURL: function(event) | |
| { | |
| InspectorFrontendHost.copyText(this.resource.url); | |
| }, | |
| _openInNewTab: function(event) | |
| { | |
| InspectorFrontendHost.openInNewTab(this.resource.url); | |
| } | |
| } | |
| WebInspector.ImageView.prototype.__proto__ = WebInspector.ResourceView.prototype; | |
| WebInspector.SplitView = function(sidebarPosition, sidebarWidthSettingName, defaultSidebarWidth) | |
| { | |
| WebInspector.View.call(this); | |
| this.registerRequiredCSS("splitView.css"); | |
| this.element.className = "split-view"; | |
| this._leftElement = document.createElement("div"); | |
| this._leftElement.className = "split-view-contents"; | |
| this.element.appendChild(this._leftElement); | |
| this._rightElement = document.createElement("div"); | |
| this._rightElement.className = "split-view-contents"; | |
| this.element.appendChild(this._rightElement); | |
| this.sidebarResizerElement = document.createElement("div"); | |
| this.sidebarResizerElement.className = "split-view-resizer"; | |
| this.installResizer(this.sidebarResizerElement); | |
| this._resizable = true; | |
| this.element.appendChild(this.sidebarResizerElement); | |
| defaultSidebarWidth = defaultSidebarWidth || 200; | |
| this._savedSidebarWidth = defaultSidebarWidth; | |
| this._sidebarWidthSettingName = sidebarWidthSettingName; | |
| if (this._sidebarWidthSettingName) | |
| WebInspector.settings[this._sidebarWidthSettingName] = WebInspector.settings.createSetting(this._sidebarWidthSettingName, undefined); | |
| this._minimalSidebarWidth = Preferences.minSidebarWidth; | |
| this._minimalMainWidth = 0; | |
| this._minimalSidebarWidthPercent = 0; | |
| this._minimalMainWidthPercent = 50; | |
| this._mainElementHidden = false; | |
| this._sidebarElementHidden = false; | |
| this._innerSetSidebarPosition(sidebarPosition || WebInspector.SplitView.SidebarPosition.Left); | |
| } | |
| WebInspector.SplitView.EventTypes = { | |
| Resized: "Resized" | |
| } | |
| WebInspector.SplitView.SidebarPosition = { | |
| Left: "Left", | |
| Right: "Right" | |
| } | |
| WebInspector.SplitView.prototype = { | |
| get hasLeftSidebar() | |
| { | |
| return this._sidebarPosition === WebInspector.SplitView.SidebarPosition.Left; | |
| }, | |
| get mainElement() | |
| { | |
| return this.hasLeftSidebar ? this._rightElement : this._leftElement; | |
| }, | |
| get sidebarElement() | |
| { | |
| return this.hasLeftSidebar ? this._leftElement : this._rightElement; | |
| }, | |
| get resizable() | |
| { | |
| return this._resizable && !this._mainElementHidden && !this._sidebarElementHidden; | |
| }, | |
| set resizable(resizable) | |
| { | |
| if (this._resizable === resizable) | |
| return; | |
| this._resizable = resizable; | |
| this._updateResizer(resizable); | |
| }, | |
| _updateResizer: function() | |
| { | |
| if (this.resizable) | |
| this.sidebarResizerElement.removeStyleClass("hidden"); | |
| else | |
| this.sidebarResizerElement.addStyleClass("hidden"); | |
| }, | |
| set sidebarPosition(sidebarPosition) | |
| { | |
| if (this._sidebarPosition === sidebarPosition) | |
| return; | |
| this._innerSetSidebarPosition(sidebarPosition); | |
| this._restoreSidebarWidth(); | |
| }, | |
| _innerSetSidebarPosition: function(sidebarPosition) | |
| { | |
| this._sidebarPosition = sidebarPosition; | |
| this._leftElement.style.left = 0; | |
| this._rightElement.style.right = 0; | |
| if (this.hasLeftSidebar) { | |
| this._leftElement.addStyleClass("split-view-sidebar-left"); | |
| this._rightElement.removeStyleClass("split-view-sidebar-right"); | |
| this._leftElement.style.removeProperty("right"); | |
| this._rightElement.style.removeProperty("width"); | |
| this.sidebarResizerElement.style.removeProperty("right"); | |
| } else { | |
| this._rightElement.addStyleClass("split-view-sidebar-right"); | |
| this._leftElement.removeStyleClass("split-view-sidebar-left"); | |
| this._leftElement.style.removeProperty("width"); | |
| this._rightElement.style.removeProperty("left"); | |
| this.sidebarResizerElement.style.removeProperty("left"); | |
| } | |
| }, | |
| set minimalSidebarWidth(width) | |
| { | |
| this._minimalSidebarWidth = width; | |
| }, | |
| set minimalMainWidth(width) | |
| { | |
| this._minimalMainWidth = width; | |
| }, | |
| set minimalSidebarWidthPercent(widthPercent) | |
| { | |
| this._minimalSidebarWidthPercent = widthPercent; | |
| }, | |
| set minimalMainWidthPercent(widthPercent) | |
| { | |
| this._minimalMainWidthPercent = widthPercent; | |
| }, | |
| setMainWidth: function(width) | |
| { | |
| this.setSidebarWidth(this._totalWidth - width); | |
| }, | |
| setSidebarWidth: function(width) | |
| { | |
| if (this._sidebarWidth === width) | |
| return; | |
| this._innerSetSidebarWidth(width); | |
| this.saveSidebarWidth(); | |
| }, | |
| sidebarWidth: function() | |
| { | |
| return this._sidebarWidth; | |
| }, | |
| _innerSetSidebarWidth: function(width) | |
| { | |
| if (this.hasLeftSidebar) | |
| this._innerSetLeftSidebarWidth(width); | |
| else | |
| this._innerSetRightSidebarWidth(width); | |
| this._sidebarWidth = width; | |
| this.doResize(); | |
| this.dispatchEventToListeners(WebInspector.SplitView.EventTypes.Resized, this._sidebarWidth); | |
| }, | |
| _innerSetLeftSidebarWidth: function(width) | |
| { | |
| this._leftElement.style.width = width + "px"; | |
| this._rightElement.style.left = width + "px"; | |
| this.sidebarResizerElement.style.left = (width - 3) + "px"; | |
| }, | |
| _innerSetRightSidebarWidth: function(width) | |
| { | |
| this._rightElement.style.width = width + "px"; | |
| this._leftElement.style.right = width + "px"; | |
| this.sidebarResizerElement.style.right = (width - 3) + "px"; | |
| }, | |
| _setSidebarWidthEnsuringConstraints: function(width) | |
| { | |
| var minWidth = Math.max(this._minimalSidebarWidth, this._totalWidth * this._minimalSidebarWidthPercent); | |
| var maxWidth = Math.min(this._totalWidth - this._minimalMainWidth, this._totalWidth * (100 - this._minimalMainWidthPercent) / 100 ); | |
| width = Number.constrain(width, minWidth, maxWidth); | |
| this.setSidebarWidth(width); | |
| }, | |
| hideMainElement: function() | |
| { | |
| if (this._mainElementHidden) | |
| return; | |
| if (this._sidebarElementHidden) | |
| this.showSidebarElement(); | |
| this.mainElement.addStyleClass("hidden"); | |
| this.sidebarElement.addStyleClass("maximized"); | |
| if (this.hasLeftSidebar) | |
| this.sidebarElement.style.right = "0px"; | |
| else | |
| this.sidebarElement.style.left = "0px"; | |
| this._mainElementHidden = true; | |
| this._updateResizer(); | |
| this._restoreSidebarWidth(); | |
| this.doResize(); | |
| }, | |
| showMainElement: function() | |
| { | |
| if (!this._mainElementHidden) | |
| return; | |
| this.mainElement.removeStyleClass("hidden"); | |
| this.sidebarElement.removeStyleClass("maximized"); | |
| if (this.hasLeftSidebar) | |
| this.sidebarElement.style.right = ""; | |
| else | |
| this.sidebarElement.style.left = ""; | |
| this._mainElementHidden = false; | |
| this._updateResizer(); | |
| this._restoreSidebarWidth(); | |
| this.doResize(); | |
| }, | |
| hideSidebarElement: function() | |
| { | |
| if (this._sidebarElementHidden) | |
| return; | |
| if (this._mainElementHidden) | |
| this.showMainElement(); | |
| this.sidebarElement.addStyleClass("hidden"); | |
| this._sidebarElementHidden = true; | |
| this._updateResizer(); | |
| this._restoreSidebarWidth(); | |
| this.doResize(); | |
| }, | |
| showSidebarElement: function() | |
| { | |
| if (!this._sidebarElementHidden) | |
| return; | |
| this.sidebarElement.removeStyleClass("hidden"); | |
| this._sidebarElementHidden = false; | |
| this._updateResizer(); | |
| this._restoreSidebarWidth(); | |
| this.doResize(); | |
| }, | |
| wasShown: function() | |
| { | |
| this._totalWidth = this.element.offsetWidth; | |
| this._restoreSidebarWidth(); | |
| }, | |
| onResize: function() | |
| { | |
| this._totalWidth = this.element.offsetWidth; | |
| if (this._mainElementHidden) | |
| this._sidebarWidth = this._totalWidth; | |
| }, | |
| _startResizerDragging: function(event) | |
| { | |
| if (!this._resizable) | |
| return false; | |
| var leftWidth = this.hasLeftSidebar ? this._sidebarWidth : this._totalWidth - this._sidebarWidth; | |
| this._dragOffset = leftWidth - event.pageX; | |
| return true; | |
| }, | |
| _resizerDragging: function(event) | |
| { | |
| var leftWidth = event.pageX + this._dragOffset; | |
| var rightWidth = this._totalWidth - leftWidth; | |
| var sidebarWidth = this.hasLeftSidebar ? leftWidth : rightWidth; | |
| this._setSidebarWidthEnsuringConstraints(sidebarWidth); | |
| event.preventDefault(); | |
| }, | |
| _endResizerDragging: function(event) | |
| { | |
| delete this._dragOffset; | |
| }, | |
| installResizer: function(resizerElement) | |
| { | |
| WebInspector.installDragHandle(resizerElement, this._startResizerDragging.bind(this), this._resizerDragging.bind(this), this._endResizerDragging.bind(this), "ew-resize"); | |
| }, | |
| preferredSidebarWidth: function() | |
| { | |
| if (!this._sidebarWidthSettingName) | |
| return this._savedSidebarWidth; | |
| return WebInspector.settings[this._sidebarWidthSettingName].get() || this._savedSidebarWidth; | |
| }, | |
| _restoreSidebarWidth: function() | |
| { | |
| if (this._mainElementHidden) { | |
| this.sidebarElement.style.width = ""; | |
| this._sidebarWidth = this._totalWidth; | |
| return; | |
| } | |
| if (this._sidebarElementHidden) { | |
| this._innerSetSidebarWidth(0); | |
| return; | |
| } | |
| this._setSidebarWidthEnsuringConstraints(this.preferredSidebarWidth()); | |
| }, | |
| saveSidebarWidth: function() | |
| { | |
| this._savedSidebarWidth = this._sidebarWidth; | |
| if (!this._sidebarWidthSettingName) | |
| return; | |
| WebInspector.settings[this._sidebarWidthSettingName].set(this._sidebarWidth); | |
| }, | |
| elementsToRestoreScrollPositionsFor: function() | |
| { | |
| return [ this.mainElement, this.sidebarElement ]; | |
| } | |
| } | |
| WebInspector.SplitView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.ConsolePanel = function() | |
| { | |
| WebInspector.Panel.call(this, "console"); | |
| WebInspector.consoleView.addEventListener(WebInspector.ConsoleView.Events.EntryAdded, this._consoleMessageAdded, this); | |
| WebInspector.consoleView.addEventListener(WebInspector.ConsoleView.Events.ConsoleCleared, this._consoleCleared, this); | |
| this._view = WebInspector.consoleView; | |
| } | |
| WebInspector.ConsolePanel.prototype = { | |
| get statusBarItems() | |
| { | |
| return this._view.statusBarItems; | |
| }, | |
| wasShown: function() | |
| { | |
| WebInspector.Panel.prototype.wasShown.call(this); | |
| if (WebInspector.drawer.visible) { | |
| WebInspector.drawer.hide(WebInspector.Drawer.AnimationType.Immediately); | |
| this._drawerWasVisible = true; | |
| } | |
| this._view.show(this.element); | |
| }, | |
| willHide: function() | |
| { | |
| if (this._drawerWasVisible) { | |
| WebInspector.drawer.show(this._view, WebInspector.Drawer.AnimationType.Immediately); | |
| delete this._drawerWasVisible; | |
| } | |
| WebInspector.Panel.prototype.willHide.call(this); | |
| }, | |
| searchCanceled: function() | |
| { | |
| this._clearCurrentSearchResultHighlight(); | |
| delete this._searchResults; | |
| delete this._searchRegex; | |
| }, | |
| performSearch: function(query) | |
| { | |
| WebInspector.searchController.updateSearchMatchesCount(0, this); | |
| this.searchCanceled(); | |
| this._searchRegex = createPlainTextSearchRegex(query, "gi"); | |
| this._searchResults = []; | |
| var messages = WebInspector.consoleView.messages; | |
| for (var i = 0; i < messages.length; i++) { | |
| if (messages[i].matchesRegex(this._searchRegex)) { | |
| this._searchResults.push(messages[i]); | |
| this._searchRegex.lastIndex = 0; | |
| } | |
| } | |
| WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this); | |
| this._currentSearchResultIndex = -1; | |
| if (this._searchResults.length) | |
| this._jumpToSearchResult(0); | |
| }, | |
| jumpToNextSearchResult: function() | |
| { | |
| if (!this._searchResults || !this._searchResults.length) | |
| return; | |
| this._jumpToSearchResult((this._currentSearchResultIndex + 1) % this._searchResults.length); | |
| }, | |
| jumpToPreviousSearchResult: function() | |
| { | |
| if (!this._searchResults || !this._searchResults.length) | |
| return; | |
| var index = this._currentSearchResultIndex - 1; | |
| if (index === -1) | |
| index = this._searchResults.length - 1; | |
| this._jumpToSearchResult(index); | |
| return true; | |
| }, | |
| _clearCurrentSearchResultHighlight: function() | |
| { | |
| if (!this._searchResults) | |
| return; | |
| var highlightedMessage = this._searchResults[this._currentSearchResultIndex]; | |
| if (highlightedMessage) | |
| highlightedMessage.clearHighlight(); | |
| this._currentSearchResultIndex = -1; | |
| }, | |
| _jumpToSearchResult: function(index) | |
| { | |
| this._clearCurrentSearchResultHighlight(); | |
| this._currentSearchResultIndex = index; | |
| WebInspector.searchController.updateCurrentMatchIndex(this._currentSearchResultIndex, this); | |
| this._searchResults[index].highlightSearchResults(this._searchRegex); | |
| }, | |
| _consoleMessageAdded: function(event) | |
| { | |
| if (!this._searchRegex || !this.isShowing()) | |
| return; | |
| var message = event.data; | |
| this._searchRegex.lastIndex = 0; | |
| if (message.matchesRegex(this._searchRegex)) { | |
| this._searchResults.push(message); | |
| WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this); | |
| } | |
| }, | |
| _consoleCleared: function() | |
| { | |
| if (!this._searchResults) | |
| return; | |
| this._clearCurrentSearchResultHighlight(); | |
| this._searchResults.length = 0; | |
| if (this.isShowing()) | |
| WebInspector.searchController.updateSearchMatchesCount(0, this); | |
| } | |
| } | |
| WebInspector.ConsolePanel.prototype.__proto__ = WebInspector.Panel.prototype; | |
| function defineCommonExtensionSymbols(apiPrivate) | |
| { | |
| if (!apiPrivate.audits) | |
| apiPrivate.audits = {}; | |
| apiPrivate.audits.Severity = { | |
| Info: "info", | |
| Warning: "warning", | |
| Severe: "severe" | |
| }; | |
| if (!apiPrivate.console) | |
| apiPrivate.console = {}; | |
| apiPrivate.console.Severity = { | |
| Tip: "tip", | |
| Debug: "debug", | |
| Log: "log", | |
| Warning: "warning", | |
| Error: "error" | |
| }; | |
| if (!apiPrivate.panels) | |
| apiPrivate.panels = {}; | |
| apiPrivate.panels.SearchAction = { | |
| CancelSearch: "cancelSearch", | |
| PerformSearch: "performSearch", | |
| NextSearchResult: "nextSearchResult", | |
| PreviousSearchResult: "previousSearchResult" | |
| }; | |
| apiPrivate.Events = { | |
| AuditStarted: "audit-started-", | |
| ButtonClicked: "button-clicked-", | |
| ConsoleMessageAdded: "console-message-added", | |
| ElementsPanelObjectSelected: "panel-objectSelected-elements", | |
| NetworkRequestFinished: "network-request-finished", | |
| Reset: "reset", | |
| OpenResource: "open-resource", | |
| PanelSearch: "panel-search-", | |
| Reload: "Reload", | |
| ResourceAdded: "resource-added", | |
| ResourceContentCommitted: "resource-content-committed", | |
| TimelineEventRecorded: "timeline-event-recorded", | |
| ViewShown: "view-shown-", | |
| ViewHidden: "view-hidden-" | |
| }; | |
| apiPrivate.Commands = { | |
| AddAuditCategory: "addAuditCategory", | |
| AddAuditResult: "addAuditResult", | |
| AddConsoleMessage: "addConsoleMessage", | |
| AddRequestHeaders: "addRequestHeaders", | |
| CreatePanel: "createPanel", | |
| CreateSidebarPane: "createSidebarPane", | |
| CreateStatusBarButton: "createStatusBarButton", | |
| EvaluateOnInspectedPage: "evaluateOnInspectedPage", | |
| GetConsoleMessages: "getConsoleMessages", | |
| GetHAR: "getHAR", | |
| GetPageResources: "getPageResources", | |
| GetRequestContent: "getRequestContent", | |
| GetResourceContent: "getResourceContent", | |
| Subscribe: "subscribe", | |
| SetOpenResourceHandler: "setOpenResourceHandler", | |
| SetResourceContent: "setResourceContent", | |
| SetSidebarContent: "setSidebarContent", | |
| SetSidebarHeight: "setSidebarHeight", | |
| SetSidebarPage: "setSidebarPage", | |
| ShowPanel: "showPanel", | |
| StopAuditCategoryRun: "stopAuditCategoryRun", | |
| Unsubscribe: "unsubscribe", | |
| UpdateAuditProgress: "updateAuditProgress", | |
| UpdateButton: "updateButton", | |
| InspectedURLChanged: "inspectedURLChanged" | |
| }; | |
| } | |
| function injectedExtensionAPI(injectedScriptId) | |
| { | |
| var apiPrivate = {}; | |
| defineCommonExtensionSymbols(apiPrivate); | |
| var commands = apiPrivate.Commands; | |
| var events = apiPrivate.Events; | |
| var userAction = false; | |
| function EventSinkImpl(type, customDispatch) | |
| { | |
| this._type = type; | |
| this._listeners = []; | |
| this._customDispatch = customDispatch; | |
| } | |
| EventSinkImpl.prototype = { | |
| addListener: function(callback) | |
| { | |
| if (typeof callback !== "function") | |
| throw "addListener: callback is not a function"; | |
| if (this._listeners.length === 0) | |
| extensionServer.sendRequest({ command: commands.Subscribe, type: this._type }); | |
| this._listeners.push(callback); | |
| extensionServer.registerHandler("notify-" + this._type, this._dispatch.bind(this)); | |
| }, | |
| removeListener: function(callback) | |
| { | |
| var listeners = this._listeners; | |
| for (var i = 0; i < listeners.length; ++i) { | |
| if (listeners[i] === callback) { | |
| listeners.splice(i, 1); | |
| break; | |
| } | |
| } | |
| if (this._listeners.length === 0) | |
| extensionServer.sendRequest({ command: commands.Unsubscribe, type: this._type }); | |
| }, | |
| _fire: function() | |
| { | |
| var listeners = this._listeners.slice(); | |
| for (var i = 0; i < listeners.length; ++i) | |
| listeners[i].apply(null, arguments); | |
| }, | |
| _dispatch: function(request) | |
| { | |
| if (this._customDispatch) | |
| this._customDispatch.call(this, request); | |
| else | |
| this._fire.apply(this, request.arguments); | |
| } | |
| } | |
| function InspectorExtensionAPI() | |
| { | |
| this.audits = new Audits(); | |
| this.inspectedWindow = new InspectedWindow(); | |
| this.panels = new Panels(); | |
| this.network = new Network(); | |
| defineDeprecatedProperty(this, "webInspector", "resources", "network"); | |
| this.timeline = new Timeline(); | |
| this.console = new ConsoleAPI(); | |
| this.onReset = new EventSink(events.Reset); | |
| } | |
| InspectorExtensionAPI.prototype = { | |
| log: function(message) | |
| { | |
| extensionServer.sendRequest({ command: commands.Log, message: message }); | |
| } | |
| } | |
| function ConsoleAPI() | |
| { | |
| this.onMessageAdded = new EventSink(events.ConsoleMessageAdded); | |
| } | |
| ConsoleAPI.prototype = { | |
| getMessages: function(callback) | |
| { | |
| extensionServer.sendRequest({ command: commands.GetConsoleMessages }, callback); | |
| }, | |
| addMessage: function(severity, text, url, line) | |
| { | |
| extensionServer.sendRequest({ command: commands.AddConsoleMessage, severity: severity, text: text, url: url, line: line }); | |
| }, | |
| get Severity() | |
| { | |
| return apiPrivate.console.Severity; | |
| } | |
| } | |
| function Network() | |
| { | |
| function dispatchRequestEvent(message) | |
| { | |
| var request = message.arguments[1]; | |
| request.__proto__ = new Request(message.arguments[0]); | |
| this._fire(request); | |
| } | |
| this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispatchRequestEvent); | |
| defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished"); | |
| this.onNavigated = new EventSink(events.InspectedURLChanged); | |
| } | |
| Network.prototype = { | |
| getHAR: function(callback) | |
| { | |
| function callbackWrapper(result) | |
| { | |
| var entries = (result && result.entries) || []; | |
| for (var i = 0; i < entries.length; ++i) { | |
| entries[i].__proto__ = new Request(entries[i]._requestId); | |
| delete entries[i]._requestId; | |
| } | |
| callback(result); | |
| } | |
| return extensionServer.sendRequest({ command: commands.GetHAR }, callback && callbackWrapper); | |
| }, | |
| addRequestHeaders: function(headers) | |
| { | |
| return extensionServer.sendRequest({ command: commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname }); | |
| } | |
| } | |
| function RequestImpl(id) | |
| { | |
| this._id = id; | |
| } | |
| RequestImpl.prototype = { | |
| getContent: function(callback) | |
| { | |
| function callbackWrapper(response) | |
| { | |
| callback(response.content, response.encoding); | |
| } | |
| extensionServer.sendRequest({ command: commands.GetRequestContent, id: this._id }, callback && callbackWrapper); | |
| } | |
| } | |
| function Panels() | |
| { | |
| var panels = { | |
| elements: new ElementsPanel() | |
| }; | |
| function panelGetter(name) | |
| { | |
| return panels[name]; | |
| } | |
| for (var panel in panels) | |
| this.__defineGetter__(panel, panelGetter.bind(null, panel)); | |
| } | |
| Panels.prototype = { | |
| create: function(title, icon, page, callback) | |
| { | |
| var id = "extension-panel-" + extensionServer.nextObjectId(); | |
| var request = { | |
| command: commands.CreatePanel, | |
| id: id, | |
| title: title, | |
| icon: icon, | |
| page: page | |
| }; | |
| extensionServer.sendRequest(request, callback && callback.bind(this, new ExtensionPanel(id))); | |
| }, | |
| setOpenResourceHandler: function(callback) | |
| { | |
| var hadHandler = extensionServer.hasHandler(events.OpenResource); | |
| if (!callback) | |
| extensionServer.unregisterHandler(events.OpenResource); | |
| else { | |
| function callbackWrapper(message) | |
| { | |
| userAction = true; | |
| try { | |
| callback.call(null, new Resource(message.resource), message.lineNumber); | |
| } finally { | |
| userAction = false; | |
| } | |
| } | |
| extensionServer.registerHandler(events.OpenResource, callbackWrapper); | |
| } | |
| if (hadHandler === !callback) | |
| extensionServer.sendRequest({ command: commands.SetOpenResourceHandler, "handlerPresent": !!callback }); | |
| }, | |
| get SearchAction() | |
| { | |
| return apiPrivate.panels.SearchAction; | |
| } | |
| } | |
| function ExtensionViewImpl(id) | |
| { | |
| this._id = id; | |
| function dispatchShowEvent(message) | |
| { | |
| var frameIndex = message.arguments[0]; | |
| this._fire(window.parent.frames[frameIndex]); | |
| } | |
| this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent); | |
| this.onHidden = new EventSink(events.ViewHidden + id); | |
| } | |
| function PanelWithSidebarImpl(id) | |
| { | |
| this._id = id; | |
| } | |
| PanelWithSidebarImpl.prototype = { | |
| createSidebarPane: function(title, callback) | |
| { | |
| var id = "extension-sidebar-" + extensionServer.nextObjectId(); | |
| var request = { | |
| command: commands.CreateSidebarPane, | |
| panel: this._id, | |
| id: id, | |
| title: title | |
| }; | |
| function callbackWrapper() | |
| { | |
| callback(new ExtensionSidebarPane(id)); | |
| } | |
| extensionServer.sendRequest(request, callback && callbackWrapper); | |
| } | |
| } | |
| PanelWithSidebarImpl.prototype.__proto__ = ExtensionViewImpl.prototype; | |
| function ElementsPanel() | |
| { | |
| var id = "elements"; | |
| PanelWithSidebar.call(this, id); | |
| this.onSelectionChanged = new EventSink(events.ElementsPanelObjectSelected); | |
| } | |
| function ExtensionPanelImpl(id) | |
| { | |
| ExtensionViewImpl.call(this, id); | |
| this.onSearch = new EventSink(events.PanelSearch + id); | |
| } | |
| ExtensionPanelImpl.prototype = { | |
| createStatusBarButton: function(iconPath, tooltipText, disabled) | |
| { | |
| var id = "button-" + extensionServer.nextObjectId(); | |
| var request = { | |
| command: commands.CreateStatusBarButton, | |
| panel: this._id, | |
| id: id, | |
| icon: iconPath, | |
| tooltip: tooltipText, | |
| disabled: !!disabled | |
| }; | |
| extensionServer.sendRequest(request); | |
| return new Button(id); | |
| }, | |
| show: function() | |
| { | |
| if (!userAction) | |
| return; | |
| var request = { | |
| command: commands.ShowPanel, | |
| id: this._id | |
| }; | |
| extensionServer.sendRequest(request); | |
| } | |
| }; | |
| ExtensionPanelImpl.prototype.__proto__ = ExtensionViewImpl.prototype; | |
| function ExtensionSidebarPaneImpl(id) | |
| { | |
| ExtensionViewImpl.call(this, id); | |
| } | |
| ExtensionSidebarPaneImpl.prototype = { | |
| setHeight: function(height) | |
| { | |
| extensionServer.sendRequest({ command: commands.SetSidebarHeight, id: this._id, height: height }); | |
| }, | |
| setExpression: function(expression, rootTitle, evaluateOptions) | |
| { | |
| var callback = extractCallbackArgument(arguments); | |
| var request = { | |
| command: commands.SetSidebarContent, | |
| id: this._id, | |
| expression: expression, | |
| rootTitle: rootTitle, | |
| evaluateOnPage: true, | |
| }; | |
| if (typeof evaluateOptions === "object") | |
| request.evaluateOptions = evaluateOptions; | |
| extensionServer.sendRequest(request, callback); | |
| }, | |
| setObject: function(jsonObject, rootTitle, callback) | |
| { | |
| extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle }, callback); | |
| }, | |
| setPage: function(page) | |
| { | |
| extensionServer.sendRequest({ command: commands.SetSidebarPage, id: this._id, page: page }); | |
| } | |
| } | |
| function ButtonImpl(id) | |
| { | |
| this._id = id; | |
| this.onClicked = new EventSink(events.ButtonClicked + id); | |
| } | |
| ButtonImpl.prototype = { | |
| update: function(iconPath, tooltipText, disabled) | |
| { | |
| var request = { | |
| command: commands.UpdateButton, | |
| id: this._id, | |
| icon: iconPath, | |
| tooltip: tooltipText, | |
| disabled: !!disabled | |
| }; | |
| extensionServer.sendRequest(request); | |
| } | |
| }; | |
| function Audits() | |
| { | |
| } | |
| Audits.prototype = { | |
| addCategory: function(displayName, resultCount) | |
| { | |
| var id = "extension-audit-category-" + extensionServer.nextObjectId(); | |
| if (typeof resultCount !== "undefined") | |
| console.warn("Passing resultCount to audits.addCategory() is deprecated. Use AuditResult.updateProgress() instead."); | |
| extensionServer.sendRequest({ command: commands.AddAuditCategory, id: id, displayName: displayName, resultCount: resultCount }); | |
| return new AuditCategory(id); | |
| } | |
| } | |
| function AuditCategoryImpl(id) | |
| { | |
| function dispatchAuditEvent(request) | |
| { | |
| var auditResult = new AuditResult(request.arguments[0]); | |
| try { | |
| this._fire(auditResult); | |
| } catch (e) { | |
| console.error("Uncaught exception in extension audit event handler: " + e); | |
| auditResult.done(); | |
| } | |
| } | |
| this._id = id; | |
| this.onAuditStarted = new EventSink(events.AuditStarted + id, dispatchAuditEvent); | |
| } | |
| function AuditResultImpl(id) | |
| { | |
| this._id = id; | |
| this.createURL = this._nodeFactory.bind(null, "url"); | |
| this.createSnippet = this._nodeFactory.bind(null, "snippet"); | |
| this.createText = this._nodeFactory.bind(null, "text"); | |
| this.createObject = this._nodeFactory.bind(null, "object"); | |
| this.createNode = this._nodeFactory.bind(null, "node"); | |
| } | |
| AuditResultImpl.prototype = { | |
| addResult: function(displayName, description, severity, details) | |
| { | |
| if (details && !(details instanceof AuditResultNode)) | |
| details = new AuditResultNode(details instanceof Array ? details : [details]); | |
| var request = { | |
| command: commands.AddAuditResult, | |
| resultId: this._id, | |
| displayName: displayName, | |
| description: description, | |
| severity: severity, | |
| details: details | |
| }; | |
| extensionServer.sendRequest(request); | |
| }, | |
| createResult: function() | |
| { | |
| return new AuditResultNode(Array.prototype.slice.call(arguments)); | |
| }, | |
| updateProgress: function(worked, totalWork) | |
| { | |
| extensionServer.sendRequest({ command: commands.UpdateAuditProgress, resultId: this._id, progress: worked / totalWork }); | |
| }, | |
| done: function() | |
| { | |
| extensionServer.sendRequest({ command: commands.StopAuditCategoryRun, resultId: this._id }); | |
| }, | |
| get Severity() | |
| { | |
| return apiPrivate.audits.Severity; | |
| }, | |
| createResourceLink: function(url, lineNumber) | |
| { | |
| return { | |
| type: "resourceLink", | |
| arguments: [url, lineNumber && lineNumber - 1] | |
| }; | |
| }, | |
| _nodeFactory: function(type) | |
| { | |
| return { | |
| type: type, | |
| arguments: Array.prototype.slice.call(arguments, 1) | |
| }; | |
| } | |
| } | |
| function AuditResultNode(contents) | |
| { | |
| this.contents = contents; | |
| this.children = []; | |
| this.expanded = false; | |
| } | |
| AuditResultNode.prototype = { | |
| addChild: function() | |
| { | |
| var node = new AuditResultNode(Array.prototype.slice.call(arguments)); | |
| this.children.push(node); | |
| return node; | |
| } | |
| }; | |
| function InspectedWindow() | |
| { | |
| function dispatchResourceEvent(message) | |
| { | |
| this._fire(new Resource(message.arguments[0])); | |
| } | |
| function dispatchResourceContentEvent(message) | |
| { | |
| this._fire(new Resource(message.arguments[0]), message.arguments[1]); | |
| } | |
| this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceEvent); | |
| this.onResourceContentCommitted = new EventSink(events.ResourceContentCommitted, dispatchResourceContentEvent); | |
| } | |
| InspectedWindow.prototype = { | |
| reload: function(optionsOrUserAgent) | |
| { | |
| var options = null; | |
| if (typeof optionsOrUserAgent === "object") | |
| options = optionsOrUserAgent; | |
| else if (typeof optionsOrUserAgent === "string") { | |
| options = { userAgent: optionsOrUserAgent }; | |
| console.warn("Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. " + | |
| "Use inspectedWindow.reload({ userAgent: value}) instead."); | |
| } | |
| return extensionServer.sendRequest({ command: commands.Reload, options: options }); | |
| }, | |
| eval: function(expression, evaluateOptions) | |
| { | |
| var callback = extractCallbackArgument(arguments); | |
| function callbackWrapper(result) | |
| { | |
| callback(result.value, result.isException); | |
| } | |
| var request = { | |
| command: commands.EvaluateOnInspectedPage, | |
| expression: expression | |
| }; | |
| if (typeof evaluateOptions === "object") | |
| request.evaluateOptions = evaluateOptions; | |
| return extensionServer.sendRequest(request, callback && callbackWrapper); | |
| }, | |
| getResources: function(callback) | |
| { | |
| function wrapResource(resourceData) | |
| { | |
| return new Resource(resourceData); | |
| } | |
| function callbackWrapper(resources) | |
| { | |
| callback(resources.map(wrapResource)); | |
| } | |
| return extensionServer.sendRequest({ command: commands.GetPageResources }, callback && callbackWrapper); | |
| } | |
| } | |
| function ResourceImpl(resourceData) | |
| { | |
| this._url = resourceData.url | |
| this._type = resourceData.type; | |
| } | |
| ResourceImpl.prototype = { | |
| get url() | |
| { | |
| return this._url; | |
| }, | |
| get type() | |
| { | |
| return this._type; | |
| }, | |
| getContent: function(callback) | |
| { | |
| function callbackWrapper(response) | |
| { | |
| callback(response.content, response.encoding); | |
| } | |
| return extensionServer.sendRequest({ command: commands.GetResourceContent, url: this._url }, callback && callbackWrapper); | |
| }, | |
| setContent: function(content, commit, callback) | |
| { | |
| return extensionServer.sendRequest({ command: commands.SetResourceContent, url: this._url, content: content, commit: commit }, callback); | |
| } | |
| } | |
| function TimelineImpl() | |
| { | |
| this.onEventRecorded = new EventSink(events.TimelineEventRecorded); | |
| } | |
| function ExtensionServerClient() | |
| { | |
| this._callbacks = {}; | |
| this._handlers = {}; | |
| this._lastRequestId = 0; | |
| this._lastObjectId = 0; | |
| this.registerHandler("callback", this._onCallback.bind(this)); | |
| var channel = new MessageChannel(); | |
| this._port = channel.port1; | |
| this._port.addEventListener("message", this._onMessage.bind(this), false); | |
| this._port.start(); | |
| window.parent.postMessage("registerExtension", [ channel.port2 ], "*"); | |
| } | |
| ExtensionServerClient.prototype = { | |
| sendRequest: function(message, callback) | |
| { | |
| if (typeof callback === "function") | |
| message.requestId = this._registerCallback(callback); | |
| return this._port.postMessage(message); | |
| }, | |
| hasHandler: function(command) | |
| { | |
| return !!this._handlers[command]; | |
| }, | |
| registerHandler: function(command, handler) | |
| { | |
| this._handlers[command] = handler; | |
| }, | |
| unregisterHandler: function(command) | |
| { | |
| delete this._handlers[command]; | |
| }, | |
| nextObjectId: function() | |
| { | |
| return injectedScriptId + "_" + ++this._lastObjectId; | |
| }, | |
| _registerCallback: function(callback) | |
| { | |
| var id = ++this._lastRequestId; | |
| this._callbacks[id] = callback; | |
| return id; | |
| }, | |
| _onCallback: function(request) | |
| { | |
| if (request.requestId in this._callbacks) { | |
| var callback = this._callbacks[request.requestId]; | |
| delete this._callbacks[request.requestId]; | |
| callback(request.result); | |
| } | |
| }, | |
| _onMessage: function(event) | |
| { | |
| var request = event.data; | |
| var handler = this._handlers[request.command]; | |
| if (handler) | |
| handler.call(this, request); | |
| } | |
| } | |
| function populateInterfaceClass(interface, implementation) | |
| { | |
| for (var member in implementation) { | |
| if (member.charAt(0) === "_") | |
| continue; | |
| var descriptor = null; | |
| for (var owner = implementation; owner && !descriptor; owner = owner.__proto__) | |
| descriptor = Object.getOwnPropertyDescriptor(owner, member); | |
| if (!descriptor) | |
| continue; | |
| if (typeof descriptor.value === "function") | |
| interface[member] = descriptor.value.bind(implementation); | |
| else if (typeof descriptor.get === "function") | |
| interface.__defineGetter__(member, descriptor.get.bind(implementation)); | |
| else | |
| Object.defineProperty(interface, member, descriptor); | |
| } | |
| } | |
| function declareInterfaceClass(implConstructor) | |
| { | |
| return function() | |
| { | |
| var impl = { __proto__: implConstructor.prototype }; | |
| implConstructor.apply(impl, arguments); | |
| populateInterfaceClass(this, impl); | |
| } | |
| } | |
| function defineDeprecatedProperty(object, className, oldName, newName) | |
| { | |
| var warningGiven = false; | |
| function getter() | |
| { | |
| if (!warningGiven) { | |
| console.warn(className + "." + oldName + " is deprecated. Use " + className + "." + newName + " instead"); | |
| warningGiven = true; | |
| } | |
| return object[newName]; | |
| } | |
| object.__defineGetter__(oldName, getter); | |
| } | |
| function extractCallbackArgument(args) | |
| { | |
| var lastArgument = args[args.length - 1]; | |
| return typeof lastArgument === "function" ? lastArgument : undefined; | |
| } | |
| var AuditCategory = declareInterfaceClass(AuditCategoryImpl); | |
| var AuditResult = declareInterfaceClass(AuditResultImpl); | |
| var Button = declareInterfaceClass(ButtonImpl); | |
| var EventSink = declareInterfaceClass(EventSinkImpl); | |
| var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl); | |
| var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl); | |
| var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl); | |
| var Request = declareInterfaceClass(RequestImpl); | |
| var Resource = declareInterfaceClass(ResourceImpl); | |
| var Timeline = declareInterfaceClass(TimelineImpl); | |
| var extensionServer = new ExtensionServerClient(); | |
| return new InspectorExtensionAPI(); | |
| } | |
| function buildPlatformExtensionAPI(extensionInfo) | |
| { | |
| function platformExtensionAPI(coreAPI) | |
| { | |
| window.webInspector = coreAPI; | |
| } | |
| return platformExtensionAPI.toString(); | |
| } | |
| function buildExtensionAPIInjectedScript(extensionInfo) | |
| { | |
| return "(function(injectedScriptHost, inspectedWindow, injectedScriptId){ " + | |
| defineCommonExtensionSymbols.toString() + ";" + | |
| injectedExtensionAPI.toString() + ";" + | |
| buildPlatformExtensionAPI(extensionInfo) + ";" + | |
| "platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" + | |
| "return {};" + | |
| "})"; | |
| } | |
| WebInspector.ExtensionAuditCategory = function(extensionOrigin, id, displayName, ruleCount) | |
| { | |
| this._extensionOrigin = extensionOrigin; | |
| this._id = id; | |
| this._displayName = displayName; | |
| this._ruleCount = ruleCount; | |
| } | |
| WebInspector.ExtensionAuditCategory.prototype = { | |
| get id() | |
| { | |
| return this._id; | |
| }, | |
| get displayName() | |
| { | |
| return this._displayName; | |
| }, | |
| run: function(requests, ruleResultCallback, categoryDoneCallback, progress) | |
| { | |
| var results = new WebInspector.ExtensionAuditCategoryResults(this, ruleResultCallback, categoryDoneCallback, progress); | |
| WebInspector.extensionServer.startAuditRun(this, results); | |
| } | |
| } | |
| WebInspector.ExtensionAuditCategoryResults = function(category, ruleResultCallback, categoryDoneCallback, progress) | |
| { | |
| this._category = category; | |
| this._ruleResultCallback = ruleResultCallback; | |
| this._categoryDoneCallback = categoryDoneCallback; | |
| this._progress = progress; | |
| this._progress.setTotalWork(1); | |
| this._expectedResults = category._ruleCount; | |
| this._actualResults = 0; | |
| this.id = category.id + "-" + ++WebInspector.ExtensionAuditCategoryResults._lastId; | |
| } | |
| WebInspector.ExtensionAuditCategoryResults.prototype = { | |
| done: function() | |
| { | |
| WebInspector.extensionServer.stopAuditRun(this); | |
| this._progress.done(); | |
| this._categoryDoneCallback(); | |
| }, | |
| addResult: function(displayName, description, severity, details) | |
| { | |
| var result = new WebInspector.AuditRuleResult(displayName); | |
| result.addChild(description); | |
| result.severity = severity; | |
| if (details) | |
| this._addNode(result, details); | |
| this._addResult(result); | |
| }, | |
| _addNode: function(parent, node) | |
| { | |
| var contents = WebInspector.auditFormatters.partiallyApply(WebInspector.ExtensionAuditFormatters, this, node.contents); | |
| var addedNode = parent.addChild(contents, node.expanded); | |
| if (node.children) { | |
| for (var i = 0; i < node.children.length; ++i) | |
| this._addNode(addedNode, node.children[i]); | |
| } | |
| }, | |
| _addResult: function(result) | |
| { | |
| this._ruleResultCallback(result); | |
| ++this._actualResults; | |
| if (typeof this._expectedResults === "number") { | |
| this._progress.setWorked(this._actualResults / this._expectedResults); | |
| if (this._actualResults === this._expectedResults) | |
| this.done(); | |
| } | |
| }, | |
| updateProgress: function(progress) | |
| { | |
| this._progress.setWorked(progress); | |
| }, | |
| evaluate: function(expression, evaluateOptions, callback) | |
| { | |
| function onEvaluate(error, result, wasThrown) | |
| { | |
| if (wasThrown) | |
| return; | |
| var object = WebInspector.RemoteObject.fromPayload(result); | |
| callback(object); | |
| } | |
| WebInspector.extensionServer.evaluate(expression, false, false, evaluateOptions, this._category._extensionOrigin, onEvaluate); | |
| } | |
| } | |
| WebInspector.ExtensionAuditFormatters = { | |
| object: function(expression, title, evaluateOptions) | |
| { | |
| var parentElement = document.createElement("div"); | |
| function onEvaluate(remoteObject) | |
| { | |
| var section = new WebInspector.ObjectPropertiesSection(remoteObject, title); | |
| section.expanded = true; | |
| section.editable = false; | |
| parentElement.appendChild(section.element); | |
| } | |
| this.evaluate(expression, evaluateOptions, onEvaluate); | |
| return parentElement; | |
| }, | |
| node: function(expression, evaluateOptions) | |
| { | |
| var parentElement = document.createElement("div"); | |
| function onNodeAvailable(nodeId) | |
| { | |
| if (!nodeId) | |
| return; | |
| var treeOutline = new WebInspector.ElementsTreeOutline(false, false, true); | |
| treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); | |
| treeOutline.element.addStyleClass("outline-disclosure"); | |
| treeOutline.setVisible(true); | |
| parentElement.appendChild(treeOutline.element); | |
| } | |
| function onEvaluate(remoteObject) | |
| { | |
| remoteObject.pushNodeToFrontend(onNodeAvailable); | |
| } | |
| this.evaluate(expression, evaluateOptions, onEvaluate); | |
| return parentElement; | |
| } | |
| } | |
| WebInspector.ExtensionAuditCategoryResults._lastId = 0; | |
| WebInspector.ExtensionServer = function() | |
| { | |
| this._clientObjects = {}; | |
| this._handlers = {}; | |
| this._subscribers = {}; | |
| this._subscriptionStartHandlers = {}; | |
| this._subscriptionStopHandlers = {}; | |
| this._extraHeaders = {}; | |
| this._requests = {}; | |
| this._lastRequestId = 0; | |
| this._registeredExtensions = {}; | |
| this._status = new WebInspector.ExtensionStatus(); | |
| var commands = WebInspector.extensionAPI.Commands; | |
| this._registerHandler(commands.AddAuditCategory, this._onAddAuditCategory.bind(this)); | |
| this._registerHandler(commands.AddAuditResult, this._onAddAuditResult.bind(this)); | |
| this._registerHandler(commands.AddConsoleMessage, this._onAddConsoleMessage.bind(this)); | |
| this._registerHandler(commands.AddRequestHeaders, this._onAddRequestHeaders.bind(this)); | |
| this._registerHandler(commands.CreatePanel, this._onCreatePanel.bind(this)); | |
| this._registerHandler(commands.CreateSidebarPane, this._onCreateSidebarPane.bind(this)); | |
| this._registerHandler(commands.CreateStatusBarButton, this._onCreateStatusBarButton.bind(this)); | |
| this._registerHandler(commands.EvaluateOnInspectedPage, this._onEvaluateOnInspectedPage.bind(this)); | |
| this._registerHandler(commands.GetHAR, this._onGetHAR.bind(this)); | |
| this._registerHandler(commands.GetConsoleMessages, this._onGetConsoleMessages.bind(this)); | |
| this._registerHandler(commands.GetPageResources, this._onGetPageResources.bind(this)); | |
| this._registerHandler(commands.GetRequestContent, this._onGetRequestContent.bind(this)); | |
| this._registerHandler(commands.GetResourceContent, this._onGetResourceContent.bind(this)); | |
| this._registerHandler(commands.Log, this._onLog.bind(this)); | |
| this._registerHandler(commands.Reload, this._onReload.bind(this)); | |
| this._registerHandler(commands.SetOpenResourceHandler, this._onSetOpenResourceHandler.bind(this)); | |
| this._registerHandler(commands.SetResourceContent, this._onSetResourceContent.bind(this)); | |
| this._registerHandler(commands.SetSidebarHeight, this._onSetSidebarHeight.bind(this)); | |
| this._registerHandler(commands.SetSidebarContent, this._onSetSidebarContent.bind(this)); | |
| this._registerHandler(commands.SetSidebarPage, this._onSetSidebarPage.bind(this)); | |
| this._registerHandler(commands.ShowPanel, this._onShowPanel.bind(this)); | |
| this._registerHandler(commands.StopAuditCategoryRun, this._onStopAuditCategoryRun.bind(this)); | |
| this._registerHandler(commands.Subscribe, this._onSubscribe.bind(this)); | |
| this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this)); | |
| this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this)); | |
| this._registerHandler(commands.UpdateAuditProgress, this._onUpdateAuditProgress.bind(this)); | |
| window.addEventListener("message", this._onWindowMessage.bind(this), false); | |
| } | |
| WebInspector.ExtensionServer.prototype = { | |
| hasExtensions: function() | |
| { | |
| return !!Object.keys(this._registeredExtensions).length; | |
| }, | |
| notifySearchAction: function(panelId, action, searchString) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.PanelSearch + panelId, action, searchString); | |
| }, | |
| notifyViewShown: function(identifier, frameIndex) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.ViewShown + identifier, frameIndex); | |
| }, | |
| notifyViewHidden: function(identifier) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.ViewHidden + identifier); | |
| }, | |
| notifyButtonClicked: function(identifier) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.ButtonClicked + identifier); | |
| }, | |
| _inspectedURLChanged: function(event) | |
| { | |
| this._requests = {}; | |
| var url = event.data; | |
| this._postNotification(WebInspector.extensionAPI.Events.InspectedURLChanged, url); | |
| }, | |
| _mainFrameNavigated: function(event) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.Reset); | |
| }, | |
| startAuditRun: function(category, auditRun) | |
| { | |
| this._clientObjects[auditRun.id] = auditRun; | |
| this._postNotification("audit-started-" + category.id, auditRun.id); | |
| }, | |
| stopAuditRun: function(auditRun) | |
| { | |
| delete this._clientObjects[auditRun.id]; | |
| }, | |
| _postNotification: function(type, vararg) | |
| { | |
| var subscribers = this._subscribers[type]; | |
| if (!subscribers) | |
| return; | |
| var message = { | |
| command: "notify-" + type, | |
| arguments: Array.prototype.slice.call(arguments, 1) | |
| }; | |
| for (var i = 0; i < subscribers.length; ++i) | |
| subscribers[i].postMessage(message); | |
| }, | |
| _onSubscribe: function(message, port) | |
| { | |
| var subscribers = this._subscribers[message.type]; | |
| if (subscribers) | |
| subscribers.push(port); | |
| else { | |
| this._subscribers[message.type] = [ port ]; | |
| if (this._subscriptionStartHandlers[message.type]) | |
| this._subscriptionStartHandlers[message.type](); | |
| } | |
| }, | |
| _onUnsubscribe: function(message, port) | |
| { | |
| var subscribers = this._subscribers[message.type]; | |
| if (!subscribers) | |
| return; | |
| subscribers.remove(port); | |
| if (!subscribers.length) { | |
| delete this._subscribers[message.type]; | |
| if (this._subscriptionStopHandlers[message.type]) | |
| this._subscriptionStopHandlers[message.type](); | |
| } | |
| }, | |
| _onAddRequestHeaders: function(message) | |
| { | |
| var id = message.extensionId; | |
| if (typeof id !== "string") | |
| return this._status.E_BADARGTYPE("extensionId", typeof id, "string"); | |
| var extensionHeaders = this._extraHeaders[id]; | |
| if (!extensionHeaders) { | |
| extensionHeaders = {}; | |
| this._extraHeaders[id] = extensionHeaders; | |
| } | |
| for (var name in message.headers) | |
| extensionHeaders[name] = message.headers[name]; | |
| var allHeaders = {}; | |
| for (var extension in this._extraHeaders) { | |
| var headers = this._extraHeaders[extension]; | |
| for (name in headers) { | |
| if (typeof headers[name] === "string") | |
| allHeaders[name] = headers[name]; | |
| } | |
| } | |
| NetworkAgent.setExtraHTTPHeaders(allHeaders); | |
| }, | |
| _onCreatePanel: function(message, port) | |
| { | |
| var id = message.id; | |
| if (id in this._clientObjects || id in WebInspector.panels) | |
| return this._status.E_EXISTS(id); | |
| var page = this._expandResourcePath(port._extensionOrigin, message.page); | |
| var panelDescriptor = new WebInspector.PanelDescriptor(id, message.title, undefined, undefined, new WebInspector.ExtensionPanel(id, page)); | |
| panelDescriptor.setIconURL(this._expandResourcePath(port._extensionOrigin, message.icon)); | |
| this._clientObjects[id] = panelDescriptor.panel(); | |
| WebInspector.inspectorView.addPanel(panelDescriptor); | |
| return this._status.OK(); | |
| }, | |
| _onShowPanel: function(message) | |
| { | |
| WebInspector.showPanel(message.id); | |
| }, | |
| _onCreateStatusBarButton: function(message, port) | |
| { | |
| var panel = this._clientObjects[message.panel]; | |
| if (!panel || !(panel instanceof WebInspector.ExtensionPanel)) | |
| return this._status.E_NOTFOUND(message.panel); | |
| var button = new WebInspector.ExtensionButton(message.id, this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled); | |
| this._clientObjects[message.id] = button; | |
| panel.addStatusBarItem(button.element); | |
| return this._status.OK(); | |
| }, | |
| _onUpdateButton: function(message, port) | |
| { | |
| var button = this._clientObjects[message.id]; | |
| if (!button || !(button instanceof WebInspector.ExtensionButton)) | |
| return this._status.E_NOTFOUND(message.id); | |
| button.update(this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled); | |
| return this._status.OK(); | |
| }, | |
| _onCreateSidebarPane: function(message) | |
| { | |
| var panel = WebInspector.panel(message.panel); | |
| if (!panel) | |
| return this._status.E_NOTFOUND(message.panel); | |
| if (!panel.sidebarElement || !panel.sidebarPanes) | |
| return this._status.E_NOTSUPPORTED(); | |
| var id = message.id; | |
| var sidebar = new WebInspector.ExtensionSidebarPane(message.title, message.id); | |
| this._clientObjects[id] = sidebar; | |
| panel.sidebarPanes[id] = sidebar; | |
| panel.sidebarElement.appendChild(sidebar.element); | |
| return this._status.OK(); | |
| }, | |
| _onSetSidebarHeight: function(message) | |
| { | |
| var sidebar = this._clientObjects[message.id]; | |
| if (!sidebar) | |
| return this._status.E_NOTFOUND(message.id); | |
| sidebar.setHeight(message.height); | |
| return this._status.OK(); | |
| }, | |
| _onSetSidebarContent: function(message, port) | |
| { | |
| var sidebar = this._clientObjects[message.id]; | |
| if (!sidebar) | |
| return this._status.E_NOTFOUND(message.id); | |
| function callback(error) | |
| { | |
| var result = error ? this._status.E_FAILED(error) : this._status.OK(); | |
| this._dispatchCallback(message.requestId, port, result); | |
| } | |
| if (message.evaluateOnPage) | |
| return sidebar.setExpression(message.expression, message.rootTitle, message.evaluateOptions, port._extensionOrigin, callback.bind(this)); | |
| sidebar.setObject(message.expression, message.rootTitle, callback.bind(this)); | |
| }, | |
| _onSetSidebarPage: function(message, port) | |
| { | |
| var sidebar = this._clientObjects[message.id]; | |
| if (!sidebar) | |
| return this._status.E_NOTFOUND(message.id); | |
| sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message.page)); | |
| }, | |
| _onSetOpenResourceHandler: function(message, port) | |
| { | |
| var name = this._registeredExtensions[port._extensionOrigin].name || ("Extension " + port._extensionOrigin); | |
| if (message.handlerPresent) | |
| WebInspector.openAnchorLocationRegistry.registerHandler(name, this._handleOpenURL.bind(this, port)); | |
| else | |
| WebInspector.openAnchorLocationRegistry.unregisterHandler(name); | |
| }, | |
| _handleOpenURL: function(port, details) | |
| { | |
| var url = details.url; | |
| var contentProvider = WebInspector.workspace.uiSourceCodeForURL(url) || WebInspector.resourceForURL(url); | |
| if (!contentProvider) | |
| return false; | |
| var lineNumber = details.lineNumber; | |
| if (typeof lineNumber === "number") | |
| lineNumber += 1; | |
| port.postMessage({ | |
| command: "open-resource", | |
| resource: this._makeResource(contentProvider), | |
| lineNumber: lineNumber | |
| }); | |
| return true; | |
| }, | |
| _onLog: function(message) | |
| { | |
| WebInspector.log(message.message); | |
| }, | |
| _onReload: function(message) | |
| { | |
| var options = (message.options || {}); | |
| NetworkAgent.setUserAgentOverride(typeof options.userAgent === "string" ? options.userAgent : ""); | |
| var injectedScript; | |
| if (options.injectedScript) { | |
| injectedScript = "((function(){" + options.injectedScript + "})(),function(){return {}})"; | |
| } | |
| PageAgent.reload(!!options.ignoreCache, injectedScript); | |
| return this._status.OK(); | |
| }, | |
| _onEvaluateOnInspectedPage: function(message, port) | |
| { | |
| function callback(error, resultPayload, wasThrown) | |
| { | |
| var result = {}; | |
| if (error) { | |
| result.isException = true; | |
| result.value = error.toString(); | |
| } else | |
| result.value = resultPayload.value; | |
| if (wasThrown) | |
| result.isException = true; | |
| this._dispatchCallback(message.requestId, port, result); | |
| } | |
| return this.evaluate(message.expression, true, true, message.evaluateOptions, port._extensionOrigin, callback.bind(this)); | |
| }, | |
| _onGetConsoleMessages: function() | |
| { | |
| return WebInspector.console.messages.map(this._makeConsoleMessage); | |
| }, | |
| _onAddConsoleMessage: function(message) | |
| { | |
| function convertSeverity(level) | |
| { | |
| switch (level) { | |
| case WebInspector.extensionAPI.console.Severity.Tip: | |
| return WebInspector.ConsoleMessage.MessageLevel.Tip; | |
| case WebInspector.extensionAPI.console.Severity.Log: | |
| return WebInspector.ConsoleMessage.MessageLevel.Log; | |
| case WebInspector.extensionAPI.console.Severity.Warning: | |
| return WebInspector.ConsoleMessage.MessageLevel.Warning; | |
| case WebInspector.extensionAPI.console.Severity.Error: | |
| return WebInspector.ConsoleMessage.MessageLevel.Error; | |
| case WebInspector.extensionAPI.console.Severity.Debug: | |
| return WebInspector.ConsoleMessage.MessageLevel.Debug; | |
| } | |
| } | |
| var level = convertSeverity(message.severity); | |
| if (!level) | |
| return this._status.E_BADARG("message.severity", message.severity); | |
| var consoleMessage = WebInspector.ConsoleMessage.create( | |
| WebInspector.ConsoleMessage.MessageSource.JS, | |
| level, | |
| message.text, | |
| WebInspector.ConsoleMessage.MessageType.Log, | |
| message.url, | |
| message.line); | |
| WebInspector.console.addMessage(consoleMessage); | |
| }, | |
| _makeConsoleMessage: function(message) | |
| { | |
| function convertLevel(level) | |
| { | |
| if (!level) | |
| return; | |
| switch (level) { | |
| case WebInspector.ConsoleMessage.MessageLevel.Tip: | |
| return WebInspector.extensionAPI.console.Severity.Tip; | |
| case WebInspector.ConsoleMessage.MessageLevel.Log: | |
| return WebInspector.extensionAPI.console.Severity.Log; | |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: | |
| return WebInspector.extensionAPI.console.Severity.Warning; | |
| case WebInspector.ConsoleMessage.MessageLevel.Error: | |
| return WebInspector.extensionAPI.console.Severity.Error; | |
| case WebInspector.ConsoleMessage.MessageLevel.Debug: | |
| return WebInspector.extensionAPI.console.Severity.Debug; | |
| default: | |
| return WebInspector.extensionAPI.console.Severity.Log; | |
| } | |
| } | |
| var result = { | |
| severity: convertLevel(message.level), | |
| text: message.text, | |
| }; | |
| if (message.url) | |
| result.url = message.url; | |
| if (message.line) | |
| result.line = message.line; | |
| return result; | |
| }, | |
| _onGetHAR: function() | |
| { | |
| var requests = WebInspector.networkLog.requests; | |
| var harLog = (new WebInspector.HARLog(requests)).build(); | |
| for (var i = 0; i < harLog.entries.length; ++i) | |
| harLog.entries[i]._requestId = this._requestId(requests[i]); | |
| return harLog; | |
| }, | |
| _makeResource: function(contentProvider) | |
| { | |
| return { | |
| url: contentProvider.contentURL(), | |
| type: contentProvider.contentType().name() | |
| }; | |
| }, | |
| _onGetPageResources: function() | |
| { | |
| var resources = {}; | |
| function pushResourceData(contentProvider) | |
| { | |
| if (!resources[contentProvider.contentURL()]) | |
| resources[contentProvider.contentURL()] = this._makeResource(contentProvider); | |
| } | |
| WebInspector.workspace.uiSourceCodes().forEach(pushResourceData.bind(this)); | |
| WebInspector.resourceTreeModel.forAllResources(pushResourceData.bind(this)); | |
| return Object.values(resources); | |
| }, | |
| _getResourceContent: function(contentProvider, message, port) | |
| { | |
| function onContentAvailable(content, contentEncoded, mimeType) | |
| { | |
| var response = { | |
| encoding: contentEncoded ? "base64" : "", | |
| content: content | |
| }; | |
| this._dispatchCallback(message.requestId, port, response); | |
| } | |
| contentProvider.requestContent(onContentAvailable.bind(this)); | |
| }, | |
| _onGetRequestContent: function(message, port) | |
| { | |
| var request = this._requestById(message.id); | |
| if (!request) | |
| return this._status.E_NOTFOUND(message.id); | |
| this._getResourceContent(request, message, port); | |
| }, | |
| _onGetResourceContent: function(message, port) | |
| { | |
| var url = message.url; | |
| var contentProvider = WebInspector.workspace.uiSourceCodeForURL(url) || WebInspector.resourceForURL(url); | |
| if (!contentProvider) | |
| return this._status.E_NOTFOUND(url); | |
| this._getResourceContent(contentProvider, message, port); | |
| }, | |
| _onSetResourceContent: function(message, port) | |
| { | |
| function callbackWrapper(error) | |
| { | |
| var response = error ? this._status.E_FAILED(error) : this._status.OK(); | |
| this._dispatchCallback(message.requestId, port, response); | |
| } | |
| var url = message.url; | |
| var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(url); | |
| if (!uiSourceCode) { | |
| var resource = WebInspector.resourceTreeModel.resourceForURL(url); | |
| if (!resource) | |
| return this._status.E_NOTFOUND(url); | |
| return this._status.E_NOTSUPPORTED("Resource is not editable") | |
| } | |
| uiSourceCode.setWorkingCopy(message.content); | |
| if (message.commit) | |
| uiSourceCode.commitWorkingCopy(callbackWrapper.bind(this)); | |
| else | |
| callbackWrapper.call(this, null); | |
| }, | |
| _requestId: function(request) | |
| { | |
| if (!request._extensionRequestId) { | |
| request._extensionRequestId = ++this._lastRequestId; | |
| this._requests[request._extensionRequestId] = request; | |
| } | |
| return request._extensionRequestId; | |
| }, | |
| _requestById: function(id) | |
| { | |
| return this._requests[id]; | |
| }, | |
| _onAddAuditCategory: function(message, port) | |
| { | |
| var category = new WebInspector.ExtensionAuditCategory(port._extensionOrigin, message.id, message.displayName, message.resultCount); | |
| if (WebInspector.panel("audits").getCategory(category.id)) | |
| return this._status.E_EXISTS(category.id); | |
| this._clientObjects[message.id] = category; | |
| WebInspector.panel("audits").addCategory(category); | |
| }, | |
| _onAddAuditResult: function(message) | |
| { | |
| var auditResult = this._clientObjects[message.resultId]; | |
| if (!auditResult) | |
| return this._status.E_NOTFOUND(message.resultId); | |
| try { | |
| auditResult.addResult(message.displayName, message.description, message.severity, message.details); | |
| } catch (e) { | |
| return e; | |
| } | |
| return this._status.OK(); | |
| }, | |
| _onUpdateAuditProgress: function(message) | |
| { | |
| var auditResult = this._clientObjects[message.resultId]; | |
| if (!auditResult) | |
| return this._status.E_NOTFOUND(message.resultId); | |
| auditResult.updateProgress(Math.min(Math.max(0, message.progress), 1)); | |
| }, | |
| _onStopAuditCategoryRun: function(message) | |
| { | |
| var auditRun = this._clientObjects[message.resultId]; | |
| if (!auditRun) | |
| return this._status.E_NOTFOUND(message.resultId); | |
| auditRun.done(); | |
| }, | |
| _dispatchCallback: function(requestId, port, result) | |
| { | |
| if (requestId) | |
| port.postMessage({ command: "callback", requestId: requestId, result: result }); | |
| }, | |
| initExtensions: function() | |
| { | |
| this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ConsoleMessageAdded, | |
| WebInspector.console, WebInspector.ConsoleModel.Events.MessageAdded, this._notifyConsoleMessageAdded); | |
| this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.NetworkRequestFinished, | |
| WebInspector.networkManager, WebInspector.NetworkManager.EventTypes.RequestFinished, this._notifyRequestFinished); | |
| this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceAdded, | |
| WebInspector.workspace, | |
| WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, | |
| this._notifyResourceAdded); | |
| this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ElementsPanelObjectSelected, | |
| WebInspector.notifications, | |
| WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, | |
| this._notifyElementsSelectionChanged); | |
| this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceContentCommitted, | |
| WebInspector.workspace, | |
| WebInspector.Workspace.Events.UISourceCodeContentCommitted, | |
| this._notifyUISourceCodeContentCommitted); | |
| function onTimelineSubscriptionStarted() | |
| { | |
| WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, | |
| this._notifyTimelineEventRecorded, this); | |
| WebInspector.timelineManager.start(); | |
| } | |
| function onTimelineSubscriptionStopped() | |
| { | |
| WebInspector.timelineManager.stop(); | |
| WebInspector.timelineManager.removeEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, | |
| this._notifyTimelineEventRecorded, this); | |
| } | |
| this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.TimelineEventRecorded, | |
| onTimelineSubscriptionStarted.bind(this), onTimelineSubscriptionStopped.bind(this)); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, | |
| this._inspectedURLChanged, this); | |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this); | |
| this._initDone = true; | |
| if (this._pendingExtensions) { | |
| this._pendingExtensions.forEach(this._innerAddExtension, this); | |
| delete this._pendingExtensions; | |
| } | |
| InspectorExtensionRegistry.getExtensionsAsync(); | |
| }, | |
| _notifyConsoleMessageAdded: function(event) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.ConsoleMessageAdded, this._makeConsoleMessage(event.data)); | |
| }, | |
| _notifyResourceAdded: function(event) | |
| { | |
| var uiSourceCode = event.data; | |
| this._postNotification(WebInspector.extensionAPI.Events.ResourceAdded, this._makeResource(uiSourceCode)); | |
| }, | |
| _notifyUISourceCodeContentCommitted: function(event) | |
| { | |
| var uiSourceCode = event.data.uiSourceCode; | |
| var content = event.data.content; | |
| this._postNotification(WebInspector.extensionAPI.Events.ResourceContentCommitted, this._makeResource(uiSourceCode), content); | |
| }, | |
| _notifyRequestFinished: function(event) | |
| { | |
| var request = event.data; | |
| this._postNotification(WebInspector.extensionAPI.Events.NetworkRequestFinished, this._requestId(request), (new WebInspector.HAREntry(request)).build()); | |
| }, | |
| _notifyElementsSelectionChanged: function() | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.ElementsPanelObjectSelected); | |
| }, | |
| _notifyTimelineEventRecorded: function(event) | |
| { | |
| this._postNotification(WebInspector.extensionAPI.Events.TimelineEventRecorded, event.data); | |
| }, | |
| _addExtensions: function(extensions) | |
| { | |
| extensions.forEach(this._addExtension, this); | |
| }, | |
| _addExtension: function(extensionInfo) | |
| { | |
| if (this._initDone) { | |
| this._innerAddExtension(extensionInfo); | |
| return; | |
| } | |
| if (this._pendingExtensions) | |
| this._pendingExtensions.push(extensionInfo); | |
| else | |
| this._pendingExtensions = [extensionInfo]; | |
| }, | |
| _innerAddExtension: function(extensionInfo) | |
| { | |
| const urlOriginRegExp = new RegExp("([^:]+:\/\/[^/]*)\/"); | |
| var startPage = extensionInfo.startPage; | |
| var name = extensionInfo.name; | |
| try { | |
| var originMatch = urlOriginRegExp.exec(startPage); | |
| if (!originMatch) { | |
| console.error("Skipping extension with invalid URL: " + startPage); | |
| return false; | |
| } | |
| var extensionOrigin = originMatch[1]; | |
| if (!this._registeredExtensions[extensionOrigin]) { | |
| InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, buildExtensionAPIInjectedScript(extensionInfo)); | |
| this._registeredExtensions[extensionOrigin] = { name: name }; | |
| } | |
| var iframe = document.createElement("iframe"); | |
| iframe.src = startPage; | |
| iframe.style.display = "none"; | |
| document.body.appendChild(iframe); | |
| } catch (e) { | |
| console.error("Failed to initialize extension " + startPage + ":" + e); | |
| return false; | |
| } | |
| return true; | |
| }, | |
| _onWindowMessage: function(event) | |
| { | |
| if (event.data === "registerExtension") | |
| this._registerExtension(event.origin, event.ports[0]); | |
| }, | |
| _registerExtension: function(origin, port) | |
| { | |
| if (!this._registeredExtensions.hasOwnProperty(origin)) { | |
| if (origin !== window.location.origin) | |
| console.error("Ignoring unauthorized client request from " + origin); | |
| return; | |
| } | |
| port._extensionOrigin = origin; | |
| port.addEventListener("message", this._onmessage.bind(this), false); | |
| port.start(); | |
| }, | |
| _onmessage: function(event) | |
| { | |
| var message = event.data; | |
| var result; | |
| if (message.command in this._handlers) | |
| result = this._handlers[message.command](message, event.target); | |
| else | |
| result = this._status.E_NOTSUPPORTED(message.command); | |
| if (result && message.requestId) | |
| this._dispatchCallback(message.requestId, event.target, result); | |
| }, | |
| _registerHandler: function(command, callback) | |
| { | |
| this._handlers[command] = callback; | |
| }, | |
| _registerSubscriptionHandler: function(eventTopic, onSubscribeFirst, onUnsubscribeLast) | |
| { | |
| this._subscriptionStartHandlers[eventTopic] = onSubscribeFirst; | |
| this._subscriptionStopHandlers[eventTopic] = onUnsubscribeLast; | |
| }, | |
| _registerAutosubscriptionHandler: function(eventTopic, eventTarget, frontendEventType, handler) | |
| { | |
| this._registerSubscriptionHandler(eventTopic, | |
| eventTarget.addEventListener.bind(eventTarget, frontendEventType, handler, this), | |
| eventTarget.removeEventListener.bind(eventTarget, frontendEventType, handler, this)); | |
| }, | |
| _expandResourcePath: function(extensionPath, resourcePath) | |
| { | |
| if (!resourcePath) | |
| return; | |
| return extensionPath + this._normalizePath(resourcePath); | |
| }, | |
| _normalizePath: function(path) | |
| { | |
| var source = path.split("/"); | |
| var result = []; | |
| for (var i = 0; i < source.length; ++i) { | |
| if (source[i] === ".") | |
| continue; | |
| if (source[i] === "") | |
| continue; | |
| if (source[i] === "..") | |
| result.pop(); | |
| else | |
| result.push(source[i]); | |
| } | |
| return "/" + result.join("/"); | |
| }, | |
| evaluate: function(expression, exposeCommandLineAPI, returnByValue, options, securityOrigin, callback) | |
| { | |
| var contextId; | |
| if (typeof options === "object" && options["useContentScriptContext"]) { | |
| var mainFrame = WebInspector.resourceTreeModel.mainFrame; | |
| if (!mainFrame) | |
| return this._status.E_FAILED("main frame not available yet"); | |
| var context = WebInspector.runtimeModel.contextByFrameAndSecurityOrigin(mainFrame, securityOrigin); | |
| if (!context) | |
| return this._status.E_NOTFOUND(securityOrigin); | |
| contextId = context.id; | |
| } | |
| RuntimeAgent.evaluate(expression, "extension", exposeCommandLineAPI, true, contextId, returnByValue, callback); | |
| } | |
| } | |
| WebInspector.ExtensionStatus = function() | |
| { | |
| function makeStatus(code, description) | |
| { | |
| var details = Array.prototype.slice.call(arguments, 2); | |
| var status = { code: code, description: description, details: details }; | |
| if (code !== "OK") { | |
| status.isError = true; | |
| console.log("Extension server error: " + String.vsprintf(description, details)); | |
| } | |
| return status; | |
| } | |
| this.OK = makeStatus.bind(null, "OK", "OK"); | |
| this.E_EXISTS = makeStatus.bind(null, "E_EXISTS", "Object already exists: %s"); | |
| this.E_BADARG = makeStatus.bind(null, "E_BADARG", "Invalid argument %s: %s"); | |
| this.E_BADARGTYPE = makeStatus.bind(null, "E_BADARGTYPE", "Invalid type for argument %s: got %s, expected %s"); | |
| this.E_NOTFOUND = makeStatus.bind(null, "E_NOTFOUND", "Object not found: %s"); | |
| this.E_NOTSUPPORTED = makeStatus.bind(null, "E_NOTSUPPORTED", "Object does not support requested operation: %s"); | |
| this.E_FAILED = makeStatus.bind(null, "E_FAILED", "Operation failed: %s"); | |
| } | |
| WebInspector.addExtensions = function(extensions) | |
| { | |
| WebInspector.extensionServer._addExtensions(extensions); | |
| } | |
| WebInspector.extensionAPI = {}; | |
| defineCommonExtensionSymbols(WebInspector.extensionAPI); | |
| WebInspector.extensionServer = new WebInspector.ExtensionServer(); | |
| window.addExtension = function(page, name) | |
| { | |
| WebInspector.extensionServer._addExtension({ | |
| startPage: page, | |
| name: name, | |
| }); | |
| } | |
| WebInspector.ExtensionView = function(id, src, className) | |
| { | |
| WebInspector.View.call(this); | |
| this.element.className = "fill"; | |
| this._id = id; | |
| this._iframe = document.createElement("iframe"); | |
| this._iframe.addEventListener("load", this._onLoad.bind(this), false); | |
| this._iframe.src = src; | |
| this._iframe.className = className; | |
| this.setDefaultFocusedElement(this._iframe); | |
| this.element.appendChild(this._iframe); | |
| } | |
| WebInspector.ExtensionView.prototype = { | |
| wasShown: function() | |
| { | |
| if (typeof this._frameIndex === "number") | |
| WebInspector.extensionServer.notifyViewShown(this._id, this._frameIndex); | |
| }, | |
| willHide: function() | |
| { | |
| if (typeof this._frameIndex === "number") | |
| WebInspector.extensionServer.notifyViewHidden(this._id); | |
| }, | |
| _onLoad: function() | |
| { | |
| this._frameIndex = Array.prototype.indexOf.call(window.frames, this._iframe.contentWindow); | |
| if (this.isShowing()) | |
| WebInspector.extensionServer.notifyViewShown(this._id, this._frameIndex); | |
| } | |
| } | |
| WebInspector.ExtensionView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.ExtensionNotifierView = function(id) | |
| { | |
| WebInspector.View.call(this); | |
| this._id = id; | |
| } | |
| WebInspector.ExtensionNotifierView.prototype = { | |
| wasShown: function() | |
| { | |
| WebInspector.extensionServer.notifyViewShown(this._id); | |
| }, | |
| willHide: function() | |
| { | |
| WebInspector.extensionServer.notifyViewHidden(this._id); | |
| } | |
| } | |
| WebInspector.ExtensionNotifierView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.ExtensionPanel = function(id, pageURL) | |
| { | |
| WebInspector.Panel.call(this, id); | |
| this.setHideOnDetach(); | |
| this._statusBarItems = []; | |
| var extensionView = new WebInspector.ExtensionView(id, pageURL, "extension panel"); | |
| extensionView.show(this.element); | |
| this.setDefaultFocusedElement(extensionView.defaultFocusedElement()); | |
| } | |
| WebInspector.ExtensionPanel.prototype = { | |
| defaultFocusedElement: function() | |
| { | |
| return WebInspector.View.prototype.defaultFocusedElement.call(this); | |
| }, | |
| get statusBarItems() | |
| { | |
| return this._statusBarItems; | |
| }, | |
| addStatusBarItem: function(element) | |
| { | |
| this._statusBarItems.push(element); | |
| }, | |
| searchCanceled: function(startingNewSearch) | |
| { | |
| WebInspector.extensionServer.notifySearchAction(this.name, WebInspector.extensionAPI.panels.SearchAction.CancelSearch); | |
| WebInspector.Panel.prototype.searchCanceled.apply(this, arguments); | |
| }, | |
| performSearch: function(query) | |
| { | |
| WebInspector.extensionServer.notifySearchAction(this.name, WebInspector.extensionAPI.panels.SearchAction.PerformSearch, query); | |
| WebInspector.Panel.prototype.performSearch.apply(this, arguments); | |
| }, | |
| jumpToNextSearchResult: function() | |
| { | |
| WebInspector.extensionServer.notifySearchAction(this.name, WebInspector.extensionAPI.panels.SearchAction.NextSearchResult); | |
| WebInspector.Panel.prototype.jumpToNextSearchResult.call(this); | |
| }, | |
| jumpToPreviousSearchResult: function() | |
| { | |
| WebInspector.extensionServer.notifySearchAction(this.name, WebInspector.extensionAPI.panels.SearchAction.PreviousSearchResult); | |
| WebInspector.Panel.prototype.jumpToPreviousSearchResult.call(this); | |
| } | |
| } | |
| WebInspector.ExtensionPanel.prototype.__proto__ = WebInspector.Panel.prototype; | |
| WebInspector.ExtensionButton = function(id, iconURL, tooltip, disabled) | |
| { | |
| this._id = id; | |
| this.element = document.createElement("button"); | |
| this.element.className = "status-bar-item extension"; | |
| this.element.addEventListener("click", this._onClicked.bind(this), false); | |
| this.update(iconURL, tooltip, disabled); | |
| } | |
| WebInspector.ExtensionButton.prototype = { | |
| update: function(iconURL, tooltip, disabled) | |
| { | |
| if (typeof iconURL === "string") | |
| this.element.style.backgroundImage = "url(" + iconURL + ")"; | |
| if (typeof tooltip === "string") | |
| this.element.title = tooltip; | |
| if (typeof disabled === "boolean") | |
| this.element.disabled = disabled; | |
| }, | |
| _onClicked: function() | |
| { | |
| WebInspector.extensionServer.notifyButtonClicked(this._id); | |
| } | |
| } | |
| WebInspector.ExtensionSidebarPane = function(title, id) | |
| { | |
| WebInspector.SidebarPane.call(this, title); | |
| this._id = id; | |
| } | |
| WebInspector.ExtensionSidebarPane.prototype = { | |
| setObject: function(object, title, callback) | |
| { | |
| this._createObjectPropertiesView(); | |
| this._setObject(WebInspector.RemoteObject.fromLocalObject(object), title, callback); | |
| }, | |
| setExpression: function(expression, title, evaluateOptions, securityOrigin, callback) | |
| { | |
| this._createObjectPropertiesView(); | |
| return WebInspector.extensionServer.evaluate(expression, true, false, evaluateOptions, securityOrigin, this._onEvaluate.bind(this, title, callback)); | |
| }, | |
| setPage: function(url) | |
| { | |
| if (this._objectPropertiesView) { | |
| this._objectPropertiesView.detach(); | |
| delete this._objectPropertiesView; | |
| } | |
| if (this._extensionView) | |
| this._extensionView.detach(true); | |
| this._extensionView = new WebInspector.ExtensionView(this._id, url, "extension fill"); | |
| this._extensionView.show(this.bodyElement); | |
| if (!this.bodyElement.style.height) | |
| this.setHeight("150px"); | |
| }, | |
| setHeight: function(height) | |
| { | |
| this.bodyElement.style.height = height; | |
| }, | |
| _onEvaluate: function(title, callback, error, result, wasThrown) | |
| { | |
| if (error) | |
| callback(error.toString()); | |
| else | |
| this._setObject(WebInspector.RemoteObject.fromPayload(result), title, callback); | |
| }, | |
| _createObjectPropertiesView: function() | |
| { | |
| if (this._objectPropertiesView) | |
| return; | |
| if (this._extensionView) { | |
| this._extensionView.detach(true); | |
| delete this._extensionView; | |
| } | |
| this._objectPropertiesView = new WebInspector.ExtensionNotifierView(this._id); | |
| this._objectPropertiesView.show(this.bodyElement); | |
| }, | |
| _setObject: function(object, title, callback) | |
| { | |
| if (!this._objectPropertiesView) { | |
| callback("operation cancelled"); | |
| return; | |
| } | |
| this._objectPropertiesView.element.removeChildren(); | |
| var section = new WebInspector.ObjectPropertiesSection(object, title); | |
| if (!title) | |
| section.headerElement.addStyleClass("hidden"); | |
| section.expanded = true; | |
| section.editable = false; | |
| this._objectPropertiesView.element.appendChild(section.element); | |
| callback(); | |
| } | |
| } | |
| WebInspector.ExtensionSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; | |
| WebInspector.EmptyView = function(text) | |
| { | |
| WebInspector.View.call(this); | |
| this._text = text; | |
| } | |
| WebInspector.EmptyView.prototype = { | |
| wasShown: function() | |
| { | |
| this.element.className = "storage-empty-view"; | |
| this.element.textContent = this._text; | |
| }, | |
| set text(text) | |
| { | |
| this._text = text; | |
| if (this.isShowing()) | |
| this.element.textContent = this._text; | |
| }, | |
| } | |
| WebInspector.EmptyView.prototype.__proto__ = WebInspector.View.prototype; | |
| WebInspector.Formatter = function() | |
| { | |
| } | |
| WebInspector.Formatter.createFormatter = function(contentType) | |
| { | |
| if (contentType === WebInspector.resourceTypes.Script || contentType === WebInspector.resourceTypes.Document) | |
| return new WebInspector.ScriptFormatter(); | |
| return new WebInspector.IdentityFormatter(); | |
| } | |
| WebInspector.Formatter.locationToPosition = function(lineEndings, lineNumber, columnNumber) | |
| { | |
| var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0; | |
| return position + columnNumber; | |
| } | |
| WebInspector.Formatter.positionToLocation = function(lineEndings, position) | |
| { | |
| var lineNumber = lineEndings.upperBound(position - 1); | |
| if (!lineNumber) | |
| var columnNumber = position; | |
| else | |
| var columnNumber = position - lineEndings[lineNumber - 1] - 1; | |
| return [lineNumber, columnNumber]; | |
| } | |
| WebInspector.Formatter.prototype = { | |
| formatContent: function(mimeType, content, callback) | |
| { | |
| } | |
| } | |
| WebInspector.ScriptFormatter = function() | |
| { | |
| this._tasks = []; | |
| } | |
| WebInspector.ScriptFormatter.prototype = { | |
| formatContent: function(mimeType, content, callback) | |
| { | |
| content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''); | |
| const method = "format"; | |
| var parameters = { mimeType: mimeType, content: content, indentString: WebInspector.settings.textEditorIndent.get() }; | |
| this._tasks.push({ data: parameters, callback: callback }); | |
| this._worker.postMessage({ method: method, params: parameters }); | |
| }, | |
| _didFormatContent: function(event) | |
| { | |
| var task = this._tasks.shift(); | |
| var originalContent = task.data.content; | |
| var formattedContent = event.data.content; | |
| var mapping = event.data["mapping"]; | |
| var sourceMapping = new WebInspector.FormatterSourceMappingImpl(originalContent.lineEndings(), formattedContent.lineEndings(), mapping); | |
| task.callback(formattedContent, sourceMapping); | |
| }, | |
| get _worker() | |
| { | |
| if (!this._cachedWorker) { | |
| this._cachedWorker = new Worker("ScriptFormatterWorker.js"); | |
| this._cachedWorker.onmessage = this._didFormatContent.bind(this); | |
| } | |
| return this._cachedWorker; | |
| } | |
| } | |
| WebInspector.IdentityFormatter = function() | |
| { | |
| this._tasks = []; | |
| } | |
| WebInspector.IdentityFormatter.prototype = { | |
| formatContent: function(mimeType, content, callback) | |
| { | |
| callback(content, new WebInspector.IdentityFormatterSourceMapping()); | |
| } | |
| } | |
| WebInspector.FormatterMappingPayload = function() | |
| { | |
| this.original = []; | |
| this.formatted = []; | |
| } | |
| WebInspector.FormatterSourceMapping = function() | |
| { | |
| } | |
| WebInspector.FormatterSourceMapping.prototype = { | |
| originalToFormatted: function(lineNumber, columnNumber) { }, | |
| formattedToOriginal: function(lineNumber, columnNumber) { } | |
| } | |
| WebInspector.IdentityFormatterSourceMapping = function() | |
| { | |
| } | |
| WebInspector.IdentityFormatterSourceMapping.prototype = { | |
| originalToFormatted: function(lineNumber, columnNumber) | |
| { | |
| return [lineNumber, columnNumber || 0]; | |
| }, | |
| formattedToOriginal: function(lineNumber, columnNumber) | |
| { | |
| return [lineNumber, columnNumber || 0]; | |
| } | |
| } | |
| WebInspector.FormatterSourceMappingImpl = function(originalLineEndings, formattedLineEndings, mapping) | |
| { | |
| this._originalLineEndings = originalLineEndings; | |
| this._formattedLineEndings = formattedLineEndings; | |
| this._mapping = mapping; | |
| } | |
| WebInspector.FormatterSourceMappingImpl.prototype = { | |
| originalToFormatted: function(lineNumber, columnNumber) | |
| { | |
| var originalPosition = WebInspector.Formatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber || 0); | |
| var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition || 0); | |
| return WebInspector.Formatter.positionToLocation(this._formattedLineEndings, formattedPosition); | |
| }, | |
| formattedToOriginal: function(lineNumber, columnNumber) | |
| { | |
| var formattedPosition = WebInspector.Formatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber || 0); | |
| var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition); | |
| return WebInspector.Formatter.positionToLocation(this._originalLineEndings, originalPosition || 0); | |
| }, | |
| _convertPosition: function(positions1, positions2, position) | |
| { | |
| var index = positions1.upperBound(position) - 1; | |
| var convertedPosition = positions2[index] + position - positions1[index]; | |
| if (index < positions2.length - 1 && convertedPosition > positions2[index + 1]) | |
| convertedPosition = positions2[index + 1]; | |
| return convertedPosition; | |
| } | |
| } | |
| WebInspector.DOMSyntaxHighlighter = function(mimeType, stripExtraWhitespace) | |
| { | |
| this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType); | |
| this._stripExtraWhitespace = stripExtraWhitespace; | |
| } | |
| WebInspector.DOMSyntaxHighlighter.prototype = { | |
| createSpan: function(content, className) | |
| { | |
| var span = document.createElement("span"); | |
| span.className = "webkit-" + className; | |
| if (this._stripExtraWhitespace) | |
| content = content.replace(/^[\n\r]*/, "").replace(/\s*$/, ""); | |
| span.appendChild(document.createTextNode(content)); | |
| return span; | |
| }, | |
| syntaxHighlightNode: function(node) | |
| { | |
| this._tokenizer.condition = this._tokenizer.createInitialCondition(); | |
| var lines = node.textContent.split("\n"); | |
| node.removeChildren(); | |
| for (var i = lines[0].length ? 0 : 1; i < lines.length; ++i) { | |
| var line = lines[i]; | |
| var plainTextStart = 0; | |
| this._tokenizer.line = line; | |
| var column = 0; | |
| do { | |
| var newColumn = this._tokenizer.nextToken(column); | |
| var tokenType = this._tokenizer.tokenType; | |
| if (tokenType) { | |
| if (column > plainTextStart) { | |
| var plainText = line.substring(plainTextStart, column); | |
| node.appendChild(document.createTextNode(plainText)); | |
| } | |
| var token = line.substring(column, newColumn); | |
| node.appendChild(this.createSpan(token, tokenType)); | |
| plainTextStart = newColumn; | |
| } | |
| column = newColumn; | |
| } while (column < line.length) | |
| if (plainTextStart < line.length) { | |
| var plainText = line.substring(plainTextStart, line.length); | |
| node.appendChild(document.createTextNode(plainText)); | |
| } | |
| if (i < lines.length - 1) | |
| node.appendChild(document.createElement("br")); | |
| } | |
| } | |
| } | |
| WebInspector.TextRange = function(startLine, startColumn, endLine, endColumn) | |
| { | |
| this.startLine = startLine; | |
| this.startColumn = startColumn; | |
| this.endLine = endLine; | |
| this.endColumn = endColumn; | |
| } | |
| WebInspector.TextRange.createFromLocation = function(line, column) | |
| { | |
| return new WebInspector.TextRange(line, column, line, column); | |
| } | |
| WebInspector.TextRange.fromObject = function (serializedTextRange) | |
| { | |
| return new WebInspector.TextRange(serializedTextRange.startLine, serializedTextRange.startColumn, serializedTextRange.endLine, serializedTextRange.endColumn); | |
| } | |
| WebInspector.TextRange.prototype = { | |
| isEmpty: function() | |
| { | |
| return this.startLine === this.endLine && this.startColumn === this.endColumn; | |
| }, | |
| get linesCount() | |
| { | |
| return this.endLine - this.startLine; | |
| }, | |
| collapseToEnd: function() | |
| { | |
| return new WebInspector.TextRange(this.endLine, this.endColumn, this.endLine, this.endColumn); | |
| }, | |
| normalize: function() | |
| { | |
| if (this.startLine > this.endLine || (this.startLine === this.endLine && this.startColumn > this.endColumn)) | |
| return new WebInspector.TextRange(this.endLine, this.endColumn, this.startLine, this.startColumn); | |
| else | |
| return this; | |
| }, | |
| clone: function() | |
| { | |
| return new WebInspector.TextRange(this.startLine, this.startColumn, this.endLine, this.endColumn); | |
| }, | |
| serializeToObject: function() | |
| { | |
| var serializedTextRange = {}; | |
| serializedTextRange.startLine = this.startLine; | |
| serializedTextRange.startColumn = this.startColumn; | |
| serializedTextRange.endLine = this.endLine; | |
| serializedTextRange.endColumn = this.endColumn; | |
| return serializedTextRange; | |
| }, | |
| compareTo: function(other) | |
| { | |
| if (this.startLine > other.startLine) | |
| return 1; | |
| if (this.startLine < other.startLine) | |
| return -1; | |
| if (this.startColumn > other.startColumn) | |
| return 1; | |
| if (this.startColumn < other.startColumn) | |
| return -1; | |
| return 0; | |
| } | |
| } | |
| WebInspector.TextEditorCommand = function(newRange, originalText) | |
| { | |
| this.newRange = newRange; | |
| this.originalText = originalText; | |
| } | |
| WebInspector.TextEditorModel = function() | |
| { | |
| this._lines = [""]; | |
| this._attributes = []; | |
| this._undoStack = []; | |
| this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/; | |
| this._lineBreak = "\n"; | |
| } | |
| WebInspector.TextEditorModel.Indent = { | |
| TwoSpaces: " ", | |
| FourSpaces: " ", | |
| EightSpaces: " ", | |
| TabCharacter: "\t" | |
| } | |
| WebInspector.TextEditorModel.Events = { | |
| TextChanged: "TextChanged" | |
| } | |
| WebInspector.TextEditorModel.endsWithBracketRegex = /[{(\[]\s*$/; | |
| WebInspector.TextEditorModel.prototype = { | |
| get linesCount() | |
| { | |
| return this._lines.length; | |
| }, | |
| text: function() | |
| { | |
| return this._lines.join(this._lineBreak); | |
| }, | |
| range: function() | |
| { | |
| return new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length); | |
| }, | |
| get lineBreak() | |
| { | |
| return this._lineBreak; | |
| }, | |
| line: function(lineNumber) | |
| { | |
| if (lineNumber >= this._lines.length) | |
| throw "Out of bounds:" + lineNumber; | |
| return this._lines[lineNumber]; | |
| }, | |
| lineLength: function(lineNumber) | |
| { | |
| return this._lines[lineNumber].length; | |
| }, | |
| setText: function(text) | |
| { | |
| text = text || ""; | |
| var range = this.range(); | |
| this._lineBreak = /\r\n/.test(text) ? "\r\n" : "\n"; | |
| var newRange = this._innerSetText(range, text); | |
| this.dispatchEventToListeners(WebInspector.TextEditorModel.Events.TextChanged, { oldRange: range, newRange: newRange}); | |
| }, | |
| editRange: function(range, text) | |
| { | |
| var originalText = this.copyRange(range); | |
| if (text === originalText) | |
| return range; | |
| var newRange = this._innerSetText(range, text); | |
| this._pushUndoableCommand(newRange, originalText); | |
| this.dispatchEventToListeners(WebInspector.TextEditorModel.Events.TextChanged, { oldRange: range, newRange: newRange }); | |
| return newRange; | |
| }, | |
| _innerSetText: function(range, text) | |
| { | |
| this._eraseRange(range); | |
| if (text === "") | |
| return new WebInspector.TextRange(range.startLine, range.startColumn, range.startLine, range.startColumn); | |
| var newLines = text.split(/\r?\n/); | |
| var prefix = this._lines[range.startLine].substring(0, range.startColumn); | |
| var suffix = this._lines[range.startLine].substring(range.startColumn); | |
| var postCaret = prefix.length; | |
| if (newLines.length === 1) { | |
| this._setLine(range.startLine, prefix + newLines[0] + suffix); | |
| postCaret += newLines[0].length; | |
| } else { | |
| this._setLine(range.startLine, prefix + newLines[0]); | |
| this._insertLines(range, newLines); | |
| this._setLine(range.startLine + newLines.length - 1, newLines[newLines.length - 1] + suffix); | |
| postCaret = newLines[newLines.length - 1].length; | |
| } | |
| return new WebInspector.TextRange(range.startLine, range.startColumn, | |
| range.startLine + newLines.length - 1, postCaret); | |
| }, | |
| _insertLines: function(range, newLines) | |
| { | |
| var lines = new Array(this._lines.length + newLines.length - 1); | |
| for (var i = 0; i <= range.startLine; ++i) | |
| lines[i] = this._lines[i]; | |
| for (var i = 1; i < newLines.length; ++i) | |
| lines[range.startLine + i] = newLines[i]; | |
| for (var i = range.startLine + newLines.length; i < lines.length; ++i) | |
| lines[i] = this._lines[i - newLines.length + 1]; | |
| this._lines = lines; | |
| var attributes = new Array(lines.length); | |
| var insertionIndex = range.startColumn ? range.startLine + 1 : range.startLine; | |
| for (var i = 0; i < insertionIndex; ++i) | |
| attributes[i] = this._attributes[i]; | |
| for (var i = insertionIndex + newLines.length - 1; i < attributes.length; ++i) | |
| attributes[i] = this._attributes[i - newLines.length + 1]; | |
| this._attributes = attributes; | |
| }, | |
| _eraseRange: function(range) | |
| { | |
| if (range.isEmpty()) | |
| return; | |
| var prefix = this._lines[range.startLine].substring(0, range.startColumn); | |
| var suffix = this._lines[range.endLine].substring(range.endColumn); | |
| if (range.endLine > range.startLine) { | |
| this._lines.splice(range.startLine + 1, range.endLine - range.startLine); | |
| this._attributes.splice(range.startColumn ? range.startLine + 1 : range.startLine, range.endLine - range.startLine); | |
| } | |
| this._setLine(range.startLine, prefix + suffix); | |
| }, | |
| _setLine: function(lineNumber, text) | |
| { | |
| this._lines[lineNumber] = text; | |
| }, | |
| wordRange: function(lineNumber, column) | |
| { | |
| return new WebInspector.TextRange(lineNumber, this.wordStart(lineNumber, column, true), lineNumber, this.wordEnd(lineNumber, column, true)); | |
| }, | |
| wordStart: function(lineNumber, column, gapless) | |
| { | |
| var line = this._lines[lineNumber]; | |
| var prefix = line.substring(0, column).split("").reverse().join(""); | |
| var prefixMatch = this._noPunctuationRegex.exec(prefix); | |
| return prefixMatch && (!gapless || prefixMatch.index === 0) ? column - prefixMatch.index - prefixMatch[0].length : column; | |
| }, | |
| wordEnd: function(lineNumber, column, gapless) | |
| { | |
| var line = this._lines[lineNumber]; | |
| var suffix = line.substring(column); | |
| var suffixMatch = this._noPunctuationRegex.exec(suffix); | |
| return suffixMatch && (!gapless || suffixMatch.index === 0) ? column + suffixMatch.index + suffixMatch[0].length : column; | |
| }, | |
| copyRange: function(range) | |
| { | |
| if (!range) | |
| range = this.range(); | |
| var clip = []; | |
| if (range.startLine === range.endLine) { | |
| clip.push(this._lines[range.startLine].substring(range.startColumn, range.endColumn)); | |
| return clip.join(this._lineBreak); | |
| } | |
| clip.push(this._lines[range.startLine].substring(range.startColumn)); | |
| for (var i = range.startLine + 1; i < range.endLine; ++i) | |
| clip.push(this._lines[i]); | |
| clip.push(this._lines[range.endLine].substring(0, range.endColumn)); | |
| return clip.join(this._lineBreak); | |
| }, | |
| setAttribute: function(line, name, value) | |
| { | |
| var attrs = this._attributes[line]; | |
| if (!attrs) { | |
| attrs = {}; | |
| this._attributes[line] = attrs; | |
| } | |
| attrs[name] = value; | |
| }, | |
| getAttribute: function(line, name) | |
| { | |
| var attrs = this._attributes[line]; | |
| return attrs ? attrs[name] : null; | |
| }, | |
| removeAttribute: function(line, name) | |
| { | |
| var attrs = this._attributes[line]; | |
| if (attrs) | |
| delete attrs[name]; | |
| }, | |
| _pushUndoableCommand: function(newRange, originalText) | |
| { | |
| var command = new WebInspector.TextEditorCommand(newRange.clone(), originalText); | |
| if (this._inUndo) | |
| this._redoStack.push(command); | |
| else { | |
| if (!this._inRedo) | |
| this._redoStack = []; | |
| this._undoStack.push(command); | |
| } | |
| return command; | |
| }, | |
| undo: function(beforeCallback, afterCallback) | |
| { | |
| if (!this._undoStack.length) | |
| return null; | |
| this._markRedoableState(); | |
| this._inUndo = true; | |
| var range = this._doUndo(this._undoStack, beforeCallback, afterCallback); | |
| delete this._inUndo; | |
| return range; | |
| }, | |
| redo: function(beforeCallback, afterCallback) | |
| { | |
| if (!this._redoStack || !this._redoStack.length) | |
| return null; | |
| this.markUndoableState(); | |
| this._inRedo = true; | |
| var range = this._doUndo(this._redoStack, beforeCallback, afterCallback); | |
| delete this._inRedo; | |
| return range; | |
| }, | |
| _doUndo: function(stack, beforeCallback, afterCallback) | |
| { | |
| var range = null; | |
| for (var i = stack.length - 1; i >= 0; --i) { | |
| var command = stack[i]; | |
| stack.length = i; | |
| if (beforeCallback) | |
| beforeCallback(); | |
| range = this.editRange(command.newRange, command.originalText); | |
| if (afterCallback) | |
| afterCallback(command.newRange, range); | |
| if (i > 0 && stack[i - 1].explicit) | |
| return range; | |
| } | |
| return range; | |
| }, | |
| markUndoableState: function() | |
| { | |
| if (this._undoStack.length) | |
| this._undoStack[this._undoStack.length - 1].explicit = true; | |
| }, | |
| _markRedoableState: function() | |
| { | |
| if (this._redoStack.length) | |
| this._redoStack[this._redoStack.length - 1].explicit = true; | |
| }, | |
| resetUndoStack: function() | |
| { | |
| this._undoStack = []; | |
| } | |
| } | |
| WebInspector.TextEditorModel.prototype.__proto__ = WebInspector.Object.prototype; | |
| WebInspector.TextEditorHighlighter = function(textModel, damageCallback) | |
| { | |
| this._textModel = textModel; | |
| this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html"); | |
| this._damageCallback = damageCallback; | |
| this._highlightChunkLimit = 1000; | |
| } | |
| WebInspector.TextEditorHighlighter._MaxLineCount = 10000; | |
| WebInspector.TextEditorHighlighter.prototype = { | |
| set mimeType(mimeType) | |
| { | |
| var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType); | |
| if (tokenizer) | |
| this._tokenizer = tokenizer; | |
| }, | |
| set highlightChunkLimit(highlightChunkLimit) | |
| { | |
| this._highlightChunkLimit = highlightChunkLimit; | |
| }, | |
| highlight: function(endLine, forceRun) | |
| { | |
| if (this._textModel.linesCount > WebInspector.TextEditorHighlighter._MaxLineCount) | |
| return; | |
| var state = this._textModel.getAttribute(endLine - 1, "highlight"); | |
| if (state && state.postConditionStringified) { | |
| return; | |
| } | |
| this._requestedEndLine = endLine; | |
| if (this._highlightTimer && !forceRun) { | |
| return; | |
| } | |
| var startLine = endLine; | |
| while (startLine > 0) { | |
| state = this._textModel.getAttribute(startLine - 1, "highlight"); | |
| if (state && state.postConditionStringified) | |
| break; | |
| startLine--; | |
| } | |
| this._highlightInChunks(startLine, endLine); | |
| }, | |
| updateHighlight: function(startLine, endLine) | |
| { | |
| if (this._textModel.linesCount > WebInspector.TextEditorHighlighter._MaxLineCount) | |
| return; | |
| this._clearHighlightState(startLine); | |
| if (startLine) { | |
| var state = this._textModel.getAttribute(startLine - 1, "highlight"); | |
| if (!state || !state.postConditionStringified) { | |
| return false; | |
| } | |
| } | |
| var restored = this._highlightLines(startLine, endLine); | |
| if (!restored) { | |
| for (var i = this._lastHighlightedLine; i < this._textModel.linesCount; ++i) { | |
| var state = this._textModel.getAttribute(i, "highlight"); | |
| if (!state && i > endLine) | |
| break; | |
| this._textModel.setAttribute(i, "highlight-outdated", state); | |
| this._textModel.removeAttribute(i, "highlight"); | |
| } | |
| if (this._highlightTimer) { | |
| clearTimeout(this._highlightTimer); | |
| this._requestedEndLine = endLine; | |
| this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._lastHighlightedLine, this._requestedEndLine), 10); | |
| } | |
| } | |
| return restored; | |
| }, | |
| _highlightInChunks: function(startLine, endLine) | |
| { | |
| delete this._highlightTimer; | |
| var state = this._textModel.getAttribute(this._requestedEndLine - 1, "highlight"); | |
| if (state && state.postConditionStringified) | |
| return; | |
| if (this._requestedEndLine !== endLine) { | |
| this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, startLine, this._requestedEndLine), 100); | |
| return; | |
| } | |
| if (this._requestedEndLine > this._textModel.linesCount) | |
| this._requestedEndLine = this._textModel.linesCount; | |
| this._highlightLines(startLine, this._requestedEndLine); | |
| if (this._lastHighlightedLine < this._requestedEndLine) | |
| this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._lastHighlightedLine, this._requestedEndLine), 10); | |
| }, | |
| _highlightLines: function(startLine, endLine) | |
| { | |
| var state = this._textModel.getAttribute(startLine - 1, "highlight"); | |
| var postConditionStringified = state ? state.postConditionStringified : JSON.stringify(this._tokenizer.createInitialCondition()); | |
| var tokensCount = 0; | |
| for (var lineNumber = startLine; lineNumber < endLine; ++lineNumber) { | |
| state = this._selectHighlightState(lineNumber, postConditionStringified); | |
| if (state.postConditionStringified) { | |
| postConditionStringified = state.postConditionStringified; | |
| } else { | |
| var lastHighlightedColumn = 0; | |
| if (state.midConditionStringified) { | |
| lastHighlightedColumn = state.lastHighlightedColumn; | |
| postConditionStringified = state.midConditionStringified; | |
| } | |
| var line = this._textModel.line(lineNumber); | |
| this._tokenizer.line = line; | |
| this._tokenizer.condition = JSON.parse(postConditionStringified); | |
| do { | |
| var newColumn = this._tokenizer.nextToken(lastHighlightedColumn); | |
| var tokenType = this._tokenizer.tokenType; | |
| if (tokenType) | |
| state[lastHighlightedColumn] = { length: newColumn - lastHighlightedColumn, tokenType: tokenType }; | |
| lastHighlightedColumn = newColumn; | |
| if (++tokensCount > this._highlightChunkLimit) | |
| break; | |
| } while (lastHighlightedColumn < line.length); | |
| postConditionStringified = JSON.stringify(this._tokenizer.condition); | |
| if (lastHighlightedColumn < line.length) { | |
| state.lastHighlightedColumn = lastHighlightedColumn; | |
| state.midConditionStringified = postConditionStringified; | |
| break; | |
| } else { | |
| delete state.lastHighlightedColumn; | |
| delete state.midConditionStringified; | |
| state.postConditionStringified = postConditionStringified; | |
| } | |
| } | |
| var nextLineState = this._textModel.getAttribute(lineNumber + 1, "highlight"); | |
| if (nextLineState && nextLineState.preConditionStringified === state.postConditionStringified) { | |
| ++lineNumber; | |
| this._damageCallback(startLine, lineNumber); | |
| for (; lineNumber < endLine; ++lineNumber) { | |
| state = this._textModel.getAttribute(lineNumber, "highlight"); | |
| if (!state || !state.postConditionStringified) | |
| break; | |
| } | |
| this._lastHighlightedLine = lineNumber; | |
| return true; | |
| } | |
| } | |
| this._damageCallback(startLine, lineNumber); | |
| this._lastHighlightedLine = lineNumber; | |
| return false; | |
| }, | |
| _selectHighlightState: function(lineNumber, preConditionStringified) | |
| { | |
| var state = this._textModel.getAttribute(lineNumber, "highlight"); | |
| if (state && state.preConditionStringified === preConditionStringified) | |
| return state; | |
| var outdatedState = this._textModel.getAttribute(lineNumber, "highlight-outdated"); | |
| if (outdatedState && outdatedState.preConditionStringified === preConditionStringified) { | |
| this._textModel.setAttribute(lineNumber, "highlight", outdatedState); | |
| this._textModel.setAttribute(lineNumber, "highlight-outdated", state); | |
| return outdatedState; | |
| } | |
| if (state) | |
| this._textModel.setAttribute(lineNumber, "highlight-outdated", state); | |
| state = {}; | |
| state.preConditionStringified = preConditionStringified; | |
| this._textModel.setAttribute(lineNumber, "highlight", state); | |
| return state; | |
| }, | |
| _clearHighlightState: function(lineNumber) | |
| { | |
| this._textModel.removeAttribute(lineNumber, "highlight"); | |
| this._textModel.removeAttribute(lineNumber, "highlight-outdated"); | |
| } | |
| } | |
| WebInspector.SourceTokenizer = function() | |
| { | |
| } | |
| WebInspector.SourceTokenizer.prototype = { | |
| set line(line) { | |
| this._line = line; | |
| }, | |
| set condition(condition) | |
| { | |
| this._condition = condition; | |
| }, | |
| get condition() | |
| { | |
| return this._condition; | |
| }, | |
| getLexCondition: function() | |
| { | |
| return this.condition.lexCondition; | |
| }, | |
| setLexCondition: function(lexCondition) | |
| { | |
| this.condition.lexCondition = lexCondition; | |
| }, | |
| _charAt: function(cursor) | |
| { | |
| return cursor < this._line.length ? this._line.charAt(cursor) : "\n"; | |
| }, | |
| createInitialCondition: function() | |
| { | |
| }, | |
| nextToken: function(cursor) | |
| { | |
| } | |
| } | |
| WebInspector.SourceTokenizer.Registry = function() { | |
| this._tokenizers = {}; | |
| this._tokenizerConstructors = { | |
| "text/css": "SourceCSSTokenizer", | |
| "text/html": "SourceHTMLTokenizer", | |
| "text/javascript": "SourceJavaScriptTokenizer", | |
| "text/x-scss": "SourceCSSTokenizer" | |
| }; | |
| } | |
| WebInspector.SourceTokenizer.Registry.getInstance = function() | |
| { | |
| if (!WebInspector.SourceTokenizer.Registry._instance) | |
| WebInspector.SourceTokenizer.Registry._instance = new WebInspector.SourceTokenizer.Registry(); | |
| return WebInspector.SourceTokenizer.Registry._instance; | |
| } | |
| WebInspector.SourceTokenizer.Registry.prototype = { | |
| getTokenizer: function(mimeType) | |
| { | |
| if (!this._tokenizerConstructors[mimeType]) | |
| return null; | |
| var tokenizerClass = this._tokenizerConstructors[mimeType]; | |
| var tokenizer = this._tokenizers[tokenizerClass]; | |
| if (!tokenizer) { | |
| tokenizer = new WebInspector[tokenizerClass](); | |
| this._tokenizers[tokenizerClass] = tokenizer; | |
| } | |
| return tokenizer; | |
| } | |
| } | |
| WebInspector.SourceCSSTokenizer = function() | |
| { | |
| WebInspector.SourceTokenizer.call(this); | |
| this._propertyKeywords = WebInspector.CSSCompletions.cssPropertiesMetainfoKeySet(); | |
| this._colorKeywords = WebInspector.CSSKeywordCompletions.colors(); | |
| this._valueKeywords = [ | |
| "above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll", | |
| "alternate", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", "arabic-indic", "armenian", "asterisks", | |
| "auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "blink", | |
| "block", "block-axis", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button", | |
| "button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator", | |
| "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic", | |
| "clear", "clip", "close-quote", "col-resize", "collapse", "compact", "condensed", "contain", "content", "content-box", "context-menu", | |
| "continuous", "copy", "cover", "crop", "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", "decimal-leading-zero", "default", | |
| "default-button", "destination-atop", "destination-in", "destination-out", "destination-over", "devanagari", "disc", "discard", "document", | |
| "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", "element", | |
| "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", "ethiopic-abegede-am-et", "ethiopic-abegede-gez", | |
| "ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et", | |
| "ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et", | |
| "ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded", | |
| "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "geometricPrecision", | |
| "georgian", "graytext", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help", | |
| "hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", | |
| "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline", | |
| "inline-axis", "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "kannada", "katakana", | |
| "katakana-iroha", "khmer", "landscape", "lao", "large", "larger", "left", "level", "lighter", "line-through", "linear", "lines", | |
| "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek", | |
| "lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-roman", "lowercase", "ltr", "malayalam", "match", "media-controls-background", | |
| "media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button", | |
| "media-rewind-button", "media-seek-back-button", "media-seek-forward-button", "media-slider", "media-sliderthumb", "media-time-remaining-display", | |
| "media-volume-slider", "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button", | |
| "menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "mix", "mongolian", "monospace", "move", "multiple", | |
| "myanmar", "n-resize", "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none", | |
| "normal", "not-allowed", "nowrap", "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", "optimizeLegibility", | |
| "optimizeSpeed", "oriya", "oromo", "outset", "outside", "overlay", "overline", "padding", "padding-box", "painted", "paused", | |
| "persian", "plus-darker", "plus-lighter", "pointer", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", | |
| "push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "relative", "repeat", "repeat-x", | |
| "repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", "s-resize", "sans-serif", | |
| "scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", | |
| "searchfield-results-decoration", "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", "single", | |
| "skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", | |
| "small", "small-caps", "small-caption", "smaller", "solid", "somali", "source-atop", "source-in", "source-out", "source-over", | |
| "space", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super", | |
| "sw-resize", "table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", | |
| "table-row", "table-row-group", "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", "thick", "thin", | |
| "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", "tigrinya-er-abegede", | |
| "tigrinya-et", "tigrinya-et-abegede", "to", "top", "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", "upper-alpha", "upper-armenian", | |
| "upper-greek", "upper-hexadecimal", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible", | |
| "visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", "window", "windowframe", "windowtext", | |
| "x-large", "x-small", "xor", "xx-large", "xx-small", "yellow", "-wap-marquee", "-webkit-activelink", "-webkit-auto", "-webkit-baseline-middle", | |
| "-webkit-body", "-webkit-box", "-webkit-center", "-webkit-control", "-webkit-focus-ring-color", "-webkit-grab", "-webkit-grabbing", | |
| "-webkit-gradient", "-webkit-inline-box", "-webkit-left", "-webkit-link", "-webkit-marquee", "-webkit-mini-control", "-webkit-nowrap", "-webkit-pictograph", | |
| "-webkit-right", "-webkit-small-control", "-webkit-text", "-webkit-xxx-large", "-webkit-zoom-in", "-webkit-zoom-out", | |
| ].keySet(); | |
| this._scssValueKeywords = [ | |
| "abs", "adjust-color", "adjust-hue", "alpha", "append", "ceil", "change-color", "comparable", "complement", "darken", "desaturate", | |
| "fade-in", "fade-out", "floor", "grayscale", "hue", "ie-hex-str", "invert", "join", "length", "lighten", | |
| "lightness", "max", "min", "mix", "nth", "opacify", "opacity", "percentage", "quote", "round", "saturate", | |
| "saturation", "scale-color", "transparentize", "type-of", "unit", "unitless", "unquote", "zip" | |
| ].keySet(); | |
| this._lexConditions = { | |
| INITIAL: 0, | |
| COMMENT: 1, | |
| DSTRING: 2, | |
| SSTRING: 3 | |
| }; | |
| this._parseConditions = { | |
| INITIAL: 0, | |
| PROPERTY: 1, | |
| PROPERTY_VALUE: 2, | |
| AT_RULE: 3, | |
| AT_MEDIA_RULE: 4 | |
| }; | |
| this.case_INITIAL = 1000; | |
| this.case_COMMENT = 1002; | |
| this.case_DSTRING = 1003; | |
| this.case_SSTRING = 1004; | |
| this.condition = this.createInitialCondition(); | |
| } | |
| WebInspector.SourceCSSTokenizer.SCSSAtRelatedKeywords = ["from", "if", "in", "through"].keySet(); | |
| WebInspector.SourceCSSTokenizer.MediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet(); | |
| WebInspector.SourceCSSTokenizer.prototype = { | |
| createInitialCondition: function() | |
| { | |
| return { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL }; | |
| }, | |
| _stringToken: function(cursor, stringEnds) | |
| { | |
| if (this._isPropertyValue()) | |
| this.tokenType = "css-string"; | |
| else | |
| this.tokenType = null; | |
| return cursor; | |
| }, | |
| _isPropertyValue: function() | |
| { | |
| return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE; | |
| }, | |
| _setParseCondition: function(condition) | |
| { | |
| this._condition.parseCondition = condition; | |
| }, | |
| nextToken: function(cursor) | |
| { | |
| var cursorOnEnter = cursor; | |
| var gotoCase = 1; | |
| var YYMARKER; | |
| while (1) { | |
| switch (gotoCase) | |
| { | |
| case 1: var yych; | |
| var yyaccept = 0; | |
| if (this.getLexCondition() < 2) { | |
| if (this.getLexCondition() < 1) { | |
| { gotoCase = this.case_INITIAL; continue; }; | |
| } else { | |
| { gotoCase = this.case_COMMENT; continue; }; | |
| } | |
| } else { | |
| if (this.getLexCondition() < 3) { | |
| { gotoCase = this.case_DSTRING; continue; }; | |
| } else { | |
| { gotoCase = this.case_SSTRING; continue; }; | |
| } | |
| } | |
| case this.case_COMMENT: | |
| yych = this._charAt(cursor); | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 4; continue; }; | |
| { gotoCase = 3; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 4; continue; }; | |
| if (yych == '*') { gotoCase = 6; continue; }; | |
| { gotoCase = 3; continue; }; | |
| } | |
| case 2: | |
| { this.tokenType = "css-comment"; return cursor; } | |
| case 3: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| { gotoCase = 12; continue; }; | |
| case 4: | |
| ++cursor; | |
| { this.tokenType = null; return cursor; } | |
| case 6: | |
| yyaccept = 1; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych == '*') { gotoCase = 9; continue; }; | |
| if (yych != '/') { gotoCase = 11; continue; }; | |
| case 7: | |
| ++cursor; | |
| this.setLexCondition(this._lexConditions.INITIAL); | |
| { this.tokenType = "css-comment"; return cursor; } | |
| case 9: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych == '*') { gotoCase = 9; continue; }; | |
| if (yych == '/') { gotoCase = 7; continue; }; | |
| case 11: | |
| yyaccept = 0; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| case 12: | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 2; continue; }; | |
| { gotoCase = 11; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 2; continue; }; | |
| if (yych == '*') { gotoCase = 9; continue; }; | |
| { gotoCase = 11; continue; }; | |
| } | |
| case this.case_DSTRING: | |
| yych = this._charAt(cursor); | |
| if (yych <= '\r') { | |
| if (yych == '\n') { gotoCase = 17; continue; }; | |
| if (yych <= '\f') { gotoCase = 16; continue; }; | |
| { gotoCase = 17; continue; }; | |
| } else { | |
| if (yych <= '"') { | |
| if (yych <= '!') { gotoCase = 16; continue; }; | |
| { gotoCase = 19; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 21; continue; }; | |
| { gotoCase = 16; continue; }; | |
| } | |
| } | |
| case 15: | |
| { return this._stringToken(cursor); } | |
| case 16: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| { gotoCase = 23; continue; }; | |
| case 17: | |
| ++cursor; | |
| case 18: | |
| { this.tokenType = null; return cursor; } | |
| case 19: | |
| ++cursor; | |
| case 20: | |
| this.setLexCondition(this._lexConditions.INITIAL); | |
| { return this._stringToken(cursor, true); } | |
| case 21: | |
| yych = this._charAt(++cursor); | |
| if (yych <= 'e') { | |
| if (yych <= '\'') { | |
| if (yych == '"') { gotoCase = 22; continue; }; | |
| if (yych <= '&') { gotoCase = 18; continue; }; | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych <= '[') { gotoCase = 18; continue; }; | |
| } else { | |
| if (yych != 'b') { gotoCase = 18; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'r') { | |
| if (yych <= 'm') { | |
| if (yych >= 'g') { gotoCase = 18; continue; }; | |
| } else { | |
| if (yych <= 'n') { gotoCase = 22; continue; }; | |
| if (yych <= 'q') { gotoCase = 18; continue; }; | |
| } | |
| } else { | |
| if (yych <= 't') { | |
| if (yych <= 's') { gotoCase = 18; continue; }; | |
| } else { | |
| if (yych != 'v') { gotoCase = 18; continue; }; | |
| } | |
| } | |
| } | |
| case 22: | |
| yyaccept = 0; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| case 23: | |
| if (yych <= '\r') { | |
| if (yych == '\n') { gotoCase = 15; continue; }; | |
| if (yych <= '\f') { gotoCase = 22; continue; }; | |
| { gotoCase = 15; continue; }; | |
| } else { | |
| if (yych <= '"') { | |
| if (yych <= '!') { gotoCase = 22; continue; }; | |
| { gotoCase = 26; continue; }; | |
| } else { | |
| if (yych != '\\') { gotoCase = 22; continue; }; | |
| } | |
| } | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= 'e') { | |
| if (yych <= '\'') { | |
| if (yych == '"') { gotoCase = 22; continue; }; | |
| if (yych >= '\'') { gotoCase = 22; continue; }; | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych >= '\\') { gotoCase = 22; continue; }; | |
| } else { | |
| if (yych == 'b') { gotoCase = 22; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'r') { | |
| if (yych <= 'm') { | |
| if (yych <= 'f') { gotoCase = 22; continue; }; | |
| } else { | |
| if (yych <= 'n') { gotoCase = 22; continue; }; | |
| if (yych >= 'r') { gotoCase = 22; continue; }; | |
| } | |
| } else { | |
| if (yych <= 't') { | |
| if (yych >= 't') { gotoCase = 22; continue; }; | |
| } else { | |
| if (yych == 'v') { gotoCase = 22; continue; }; | |
| } | |
| } | |
| } | |
| cursor = YYMARKER; | |
| { gotoCase = 15; continue; }; | |
| case 26: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| { gotoCase = 20; continue; }; | |
| case this.case_INITIAL: | |
| yych = this._charAt(cursor); | |
| if (yych <= ':') { | |
| if (yych <= '&') { | |
| if (yych <= '"') { | |
| if (yych <= ' ') { gotoCase = 29; continue; }; | |
| if (yych <= '!') { gotoCase = 31; continue; }; | |
| { gotoCase = 33; continue; }; | |
| } else { | |
| if (yych <= '#') { gotoCase = 34; continue; }; | |
| if (yych <= '$') { gotoCase = 35; continue; }; | |
| if (yych >= '&') { gotoCase = 31; continue; }; | |
| } | |
| } else { | |
| if (yych <= '-') { | |
| if (yych <= '\'') { gotoCase = 36; continue; }; | |
| if (yych >= '-') { gotoCase = 37; continue; }; | |
| } else { | |
| if (yych <= '.') { gotoCase = 38; continue; }; | |
| if (yych <= '/') { gotoCase = 39; continue; }; | |
| if (yych <= '9') { gotoCase = 40; continue; }; | |
| { gotoCase = 42; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= ']') { | |
| if (yych <= '=') { | |
| if (yych <= ';') { gotoCase = 44; continue; }; | |
| if (yych >= '=') { gotoCase = 31; continue; }; | |
| } else { | |
| if (yych <= '?') { gotoCase = 29; continue; }; | |
| if (yych != '\\') { gotoCase = 31; continue; }; | |
| } | |
| } else { | |
| if (yych <= 'z') { | |
| if (yych == '_') { gotoCase = 31; continue; }; | |
| if (yych >= 'a') { gotoCase = 31; continue; }; | |
| } else { | |
| if (yych <= '{') { gotoCase = 46; continue; }; | |
| if (yych == '}') { gotoCase = 48; continue; }; | |
| } | |
| } | |
| } | |
| case 29: | |
| ++cursor; | |
| case 30: | |
| { this.tokenType = null; return cursor; } | |
| case 31: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| { gotoCase = 51; continue; }; | |
| case 32: | |
| { | |
| var token = this._line.substring(cursorOnEnter, cursor); | |
| this.tokenType = null; | |
| if (this._condition.parseCondition === this._parseConditions.INITIAL || this._condition.parseCondition === this._parseConditions.PROPERTY) { | |
| if (token.charAt(0) === "@") { | |
| this.tokenType = "css-at-rule"; | |
| this._setParseCondition(token === "@media" ? this._parseConditions.AT_MEDIA_RULE : this._parseConditions.AT_RULE); | |
| this._condition.atKeyword = token; | |
| } else if (this._condition.parseCondition === this._parseConditions.INITIAL) | |
| this.tokenType = "css-selector"; | |
| else if (this._propertyKeywords.hasOwnProperty(token)) | |
| this.tokenType = "css-property"; | |
| } else if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE || this._condition.parseCondition === this._parseConditions.AT_RULE) { | |
| if (WebInspector.SourceCSSTokenizer.SCSSAtRelatedKeywords.hasOwnProperty(token)) | |
| this.tokenType = "css-at-rule"; | |
| else if (WebInspector.SourceCSSTokenizer.MediaTypes.hasOwnProperty(token)) | |
| this.tokenType = "css-keyword"; | |
| } | |
| if (this.tokenType) | |
| return cursor; | |
| if (this._isPropertyValue()) { | |
| var firstChar = token.charAt(0); | |
| if (firstChar === "$") | |
| this.tokenType = "scss-variable"; | |
| else if (firstChar === "!") | |
| this.tokenType = "css-bang-keyword"; | |
| else if (this._condition.atKeyword === "@extend") | |
| this.tokenType = "css-selector"; | |
| else if (this._valueKeywords.hasOwnProperty(token) || this._scssValueKeywords.hasOwnProperty(token)) | |
| this.tokenType = "css-keyword"; | |
| else if (this._colorKeywords.hasOwnProperty(token)) { | |
| this.tokenType = "css-color"; | |
| } | |
| } else if (this._condition.parseCondition !== this._parseConditions.PROPERTY_VALUE) | |
| this.tokenType = "css-selector"; | |
| return cursor; | |
| } | |
| case 33: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych <= '.') { | |
| if (yych <= '!') { | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 32; continue; }; | |
| { gotoCase = 132; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 32; continue; }; | |
| if (yych <= ' ') { gotoCase = 132; continue; }; | |
| { gotoCase = 130; continue; }; | |
| } | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '"') { gotoCase = 116; continue; }; | |
| if (yych <= '%') { gotoCase = 132; continue; }; | |
| { gotoCase = 130; continue; }; | |
| } else { | |
| if (yych == '-') { gotoCase = 130; continue; }; | |
| { gotoCase = 132; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych <= '=') { | |
| if (yych <= '9') { gotoCase = 130; continue; }; | |
| if (yych <= '<') { gotoCase = 132; continue; }; | |
| { gotoCase = 130; continue; }; | |
| } else { | |
| if (yych <= '?') { gotoCase = 132; continue; }; | |
| if (yych <= '[') { gotoCase = 130; continue; }; | |
| { gotoCase = 134; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych == '^') { gotoCase = 132; continue; }; | |
| { gotoCase = 130; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 132; continue; }; | |
| if (yych <= 'z') { gotoCase = 130; continue; }; | |
| { gotoCase = 132; continue; }; | |
| } | |
| } | |
| } | |
| case 34: | |
| yych = this._charAt(++cursor); | |
| if (yych <= '@') { | |
| if (yych <= '/') { gotoCase = 30; continue; }; | |
| if (yych <= '9') { gotoCase = 127; continue; }; | |
| { gotoCase = 30; continue; }; | |
| } else { | |
| if (yych <= 'Z') { gotoCase = 127; continue; }; | |
| if (yych <= '`') { gotoCase = 30; continue; }; | |
| if (yych <= 'z') { gotoCase = 127; continue; }; | |
| { gotoCase = 30; continue; }; | |
| } | |
| case 35: | |
| yych = this._charAt(++cursor); | |
| if (yych <= '<') { | |
| if (yych <= '\'') { | |
| if (yych <= ' ') { gotoCase = 30; continue; }; | |
| if (yych <= '"') { gotoCase = 124; continue; }; | |
| if (yych <= '%') { gotoCase = 30; continue; }; | |
| { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych <= '-') { | |
| if (yych <= ',') { gotoCase = 30; continue; }; | |
| { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych <= '.') { gotoCase = 30; continue; }; | |
| if (yych <= '9') { gotoCase = 124; continue; }; | |
| { gotoCase = 30; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= ']') { | |
| if (yych <= '?') { | |
| if (yych <= '=') { gotoCase = 124; continue; }; | |
| { gotoCase = 30; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 30; continue; }; | |
| { gotoCase = 124; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych <= '^') { gotoCase = 30; continue; }; | |
| { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 30; continue; }; | |
| if (yych <= 'z') { gotoCase = 124; continue; }; | |
| { gotoCase = 30; continue; }; | |
| } | |
| } | |
| } | |
| case 36: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych <= '.') { | |
| if (yych <= '"') { | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 32; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 32; continue; }; | |
| if (yych <= ' ') { gotoCase = 118; continue; }; | |
| { gotoCase = 114; continue; }; | |
| } | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '%') { gotoCase = 118; continue; }; | |
| if (yych <= '&') { gotoCase = 114; continue; }; | |
| { gotoCase = 116; continue; }; | |
| } else { | |
| if (yych == '-') { gotoCase = 114; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych <= '=') { | |
| if (yych <= '9') { gotoCase = 114; continue; }; | |
| if (yych <= '<') { gotoCase = 118; continue; }; | |
| { gotoCase = 114; continue; }; | |
| } else { | |
| if (yych <= '?') { gotoCase = 118; continue; }; | |
| if (yych <= '[') { gotoCase = 114; continue; }; | |
| { gotoCase = 120; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych == '^') { gotoCase = 118; continue; }; | |
| { gotoCase = 114; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 118; continue; }; | |
| if (yych <= 'z') { gotoCase = 114; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } | |
| } | |
| } | |
| case 37: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych == '.') { gotoCase = 67; continue; }; | |
| if (yych <= '/') { gotoCase = 51; continue; }; | |
| if (yych <= '9') { gotoCase = 52; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 38: | |
| yych = this._charAt(++cursor); | |
| if (yych <= '/') { gotoCase = 30; continue; }; | |
| if (yych <= '9') { gotoCase = 70; continue; }; | |
| { gotoCase = 30; continue; }; | |
| case 39: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych == '*') { gotoCase = 106; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 40: | |
| yyaccept = 1; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| switch (yych) { | |
| case '!': | |
| case '"': | |
| case '&': | |
| case '\'': | |
| case '-': | |
| case '/': | |
| case '=': | |
| case '@': | |
| case 'A': | |
| case 'B': | |
| case 'C': | |
| case 'D': | |
| case 'E': | |
| case 'F': | |
| case 'G': | |
| case 'I': | |
| case 'J': | |
| case 'K': | |
| case 'L': | |
| case 'M': | |
| case 'N': | |
| case 'O': | |
| case 'P': | |
| case 'Q': | |
| case 'R': | |
| case 'S': | |
| case 'T': | |
| case 'U': | |
| case 'V': | |
| case 'W': | |
| case 'X': | |
| case 'Y': | |
| case 'Z': | |
| case '[': | |
| case ']': | |
| case 'a': | |
| case 'b': | |
| case 'f': | |
| case 'h': | |
| case 'j': | |
| case 'l': | |
| case 'n': | |
| case 'o': | |
| case 'q': | |
| case 'u': | |
| case 'v': | |
| case 'w': | |
| case 'x': | |
| case 'y': | |
| case 'z': { gotoCase = 50; continue; }; | |
| case '%': { gotoCase = 69; continue; }; | |
| case '.': { gotoCase = 67; continue; }; | |
| case '0': | |
| case '1': | |
| case '2': | |
| case '3': | |
| case '4': | |
| case '5': | |
| case '6': | |
| case '7': | |
| case '8': | |
| case '9': { gotoCase = 52; continue; }; | |
| case 'H': { gotoCase = 54; continue; }; | |
| case '_': { gotoCase = 55; continue; }; | |
| case 'c': { gotoCase = 56; continue; }; | |
| case 'd': { gotoCase = 57; continue; }; | |
| case 'e': { gotoCase = 58; continue; }; | |
| case 'g': { gotoCase = 59; continue; }; | |
| case 'i': { gotoCase = 60; continue; }; | |
| case 'k': { gotoCase = 61; continue; }; | |
| case 'm': { gotoCase = 62; continue; }; | |
| case 'p': { gotoCase = 63; continue; }; | |
| case 'r': { gotoCase = 64; continue; }; | |
| case 's': { gotoCase = 65; continue; }; | |
| case 't': { gotoCase = 66; continue; }; | |
| default: { gotoCase = 41; continue; }; | |
| } | |
| case 41: | |
| { | |
| if (this._isPropertyValue()) | |
| this.tokenType = "css-number"; | |
| else | |
| this.tokenType = null; | |
| return cursor; | |
| } | |
| case 42: | |
| ++cursor; | |
| { | |
| this.tokenType = null; | |
| if (this._condition.parseCondition === this._parseConditions.PROPERTY || this._condition.parseCondition === this._parseConditions.INITIAL) | |
| this._setParseCondition(this._parseConditions.PROPERTY_VALUE); | |
| return cursor; | |
| } | |
| case 44: | |
| ++cursor; | |
| { | |
| this.tokenType = null; | |
| this._setParseCondition(this._condition.openBraces ? this._parseConditions.PROPERTY : this._parseConditions.INITIAL); | |
| delete this._condition.atKeyword; | |
| return cursor; | |
| } | |
| case 46: | |
| ++cursor; | |
| { | |
| this.tokenType = "block-start"; | |
| this._condition.openBraces = (this._condition.openBraces || 0) + 1; | |
| if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE) | |
| this._setParseCondition(this._parseConditions.INITIAL); | |
| else | |
| this._setParseCondition(this._parseConditions.PROPERTY); | |
| return cursor; | |
| } | |
| case 48: | |
| ++cursor; | |
| { | |
| this.tokenType = "block-end"; | |
| if (this._condition.openBraces > 0) | |
| --this._condition.openBraces; | |
| this._setParseCondition(this._condition.openBraces ? this._parseConditions.PROPERTY : this._parseConditions.INITIAL); | |
| delete this._condition.atKeyword; | |
| return cursor; | |
| } | |
| case 50: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| case 51: | |
| if (yych <= '<') { | |
| if (yych <= '\'') { | |
| if (yych <= ' ') { gotoCase = 32; continue; }; | |
| if (yych <= '"') { gotoCase = 50; continue; }; | |
| if (yych <= '%') { gotoCase = 32; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '-') { | |
| if (yych <= ',') { gotoCase = 32; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '.') { gotoCase = 32; continue; }; | |
| if (yych <= '9') { gotoCase = 50; continue; }; | |
| { gotoCase = 32; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= ']') { | |
| if (yych <= '?') { | |
| if (yych <= '=') { gotoCase = 50; continue; }; | |
| { gotoCase = 32; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 32; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych <= '^') { gotoCase = 32; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 32; continue; }; | |
| if (yych <= 'z') { gotoCase = 50; continue; }; | |
| { gotoCase = 32; continue; }; | |
| } | |
| } | |
| } | |
| case 52: | |
| yyaccept = 1; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| switch (yych) { | |
| case '!': | |
| case '"': | |
| case '&': | |
| case '\'': | |
| case '-': | |
| case '/': | |
| case '=': | |
| case '@': | |
| case 'A': | |
| case 'B': | |
| case 'C': | |
| case 'D': | |
| case 'E': | |
| case 'F': | |
| case 'G': | |
| case 'I': | |
| case 'J': | |
| case 'K': | |
| case 'L': | |
| case 'M': | |
| case 'N': | |
| case 'O': | |
| case 'P': | |
| case 'Q': | |
| case 'R': | |
| case 'S': | |
| case 'T': | |
| case 'U': | |
| case 'V': | |
| case 'W': | |
| case 'X': | |
| case 'Y': | |
| case 'Z': | |
| case '[': | |
| case ']': | |
| case 'a': | |
| case 'b': | |
| case 'f': | |
| case 'h': | |
| case 'j': | |
| case 'l': | |
| case 'n': | |
| case 'o': | |
| case 'q': | |
| case 'u': | |
| case 'v': | |
| case 'w': | |
| case 'x': | |
| case 'y': | |
| case 'z': { gotoCase = 50; continue; }; | |
| case '%': { gotoCase = 69; continue; }; | |
| case '.': { gotoCase = 67; continue; }; | |
| case '0': | |
| case '1': | |
| case '2': | |
| case '3': | |
| case '4': | |
| case '5': | |
| case '6': | |
| case '7': | |
| case '8': | |
| case '9': { gotoCase = 52; continue; }; | |
| case 'H': { gotoCase = 54; continue; }; | |
| case '_': { gotoCase = 55; continue; }; | |
| case 'c': { gotoCase = 56; continue; }; | |
| case 'd': { gotoCase = 57; continue; }; | |
| case 'e': { gotoCase = 58; continue; }; | |
| case 'g': { gotoCase = 59; continue; }; | |
| case 'i': { gotoCase = 60; continue; }; | |
| case 'k': { gotoCase = 61; continue; }; | |
| case 'm': { gotoCase = 62; continue; }; | |
| case 'p': { gotoCase = 63; continue; }; | |
| case 'r': { gotoCase = 64; continue; }; | |
| case 's': { gotoCase = 65; continue; }; | |
| case 't': { gotoCase = 66; continue; }; | |
| default: { gotoCase = 41; continue; }; | |
| } | |
| case 54: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'z') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 55: | |
| yych = this._charAt(++cursor); | |
| if (yych == '_') { gotoCase = 103; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 56: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 57: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'e') { gotoCase = 102; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 58: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 65; continue; }; | |
| if (yych == 'x') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 59: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'r') { gotoCase = 100; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 60: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'n') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 61: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'H') { gotoCase = 99; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 62: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 65; continue; }; | |
| if (yych == 's') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 63: | |
| yych = this._charAt(++cursor); | |
| if (yych <= 's') { | |
| if (yych == 'c') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| } else { | |
| if (yych <= 't') { gotoCase = 65; continue; }; | |
| if (yych == 'x') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| } | |
| case 64: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'a') { gotoCase = 97; continue; }; | |
| if (yych == 'e') { gotoCase = 98; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 65: | |
| yych = this._charAt(++cursor); | |
| if (yych <= '<') { | |
| if (yych <= '\'') { | |
| if (yych <= ' ') { gotoCase = 41; continue; }; | |
| if (yych <= '"') { gotoCase = 50; continue; }; | |
| if (yych <= '%') { gotoCase = 41; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '-') { | |
| if (yych <= ',') { gotoCase = 41; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '.') { gotoCase = 41; continue; }; | |
| if (yych <= '9') { gotoCase = 50; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= ']') { | |
| if (yych <= '?') { | |
| if (yych <= '=') { gotoCase = 50; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 41; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych <= '^') { gotoCase = 41; continue; }; | |
| { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 41; continue; }; | |
| if (yych <= 'z') { gotoCase = 50; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } | |
| } | |
| } | |
| case 66: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'u') { gotoCase = 95; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 67: | |
| yych = this._charAt(++cursor); | |
| if (yych <= '/') { gotoCase = 68; continue; }; | |
| if (yych <= '9') { gotoCase = 70; continue; }; | |
| case 68: | |
| cursor = YYMARKER; | |
| if (yyaccept <= 0) { | |
| { gotoCase = 32; continue; }; | |
| } else { | |
| { gotoCase = 41; continue; }; | |
| } | |
| case 69: | |
| yych = this._charAt(++cursor); | |
| { gotoCase = 41; continue; }; | |
| case 70: | |
| yyaccept = 1; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= 'f') { | |
| if (yych <= 'H') { | |
| if (yych <= '/') { | |
| if (yych == '%') { gotoCase = 69; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } else { | |
| if (yych <= '9') { gotoCase = 70; continue; }; | |
| if (yych <= 'G') { gotoCase = 41; continue; }; | |
| { gotoCase = 82; continue; }; | |
| } | |
| } else { | |
| if (yych <= 'b') { | |
| if (yych == '_') { gotoCase = 74; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } else { | |
| if (yych <= 'c') { gotoCase = 76; continue; }; | |
| if (yych <= 'd') { gotoCase = 79; continue; }; | |
| if (yych >= 'f') { gotoCase = 41; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'm') { | |
| if (yych <= 'i') { | |
| if (yych <= 'g') { gotoCase = 80; continue; }; | |
| if (yych <= 'h') { gotoCase = 41; continue; }; | |
| { gotoCase = 78; continue; }; | |
| } else { | |
| if (yych == 'k') { gotoCase = 83; continue; }; | |
| if (yych <= 'l') { gotoCase = 41; continue; }; | |
| { gotoCase = 77; continue; }; | |
| } | |
| } else { | |
| if (yych <= 'q') { | |
| if (yych == 'p') { gotoCase = 75; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } else { | |
| if (yych <= 'r') { gotoCase = 73; continue; }; | |
| if (yych <= 's') { gotoCase = 69; continue; }; | |
| if (yych <= 't') { gotoCase = 81; continue; }; | |
| { gotoCase = 41; continue; }; | |
| } | |
| } | |
| } | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 69; continue; }; | |
| if (yych == 'x') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 73: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'a') { gotoCase = 93; continue; }; | |
| if (yych == 'e') { gotoCase = 94; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 74: | |
| yych = this._charAt(++cursor); | |
| if (yych == '_') { gotoCase = 90; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 75: | |
| yych = this._charAt(++cursor); | |
| if (yych <= 's') { | |
| if (yych == 'c') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } else { | |
| if (yych <= 't') { gotoCase = 69; continue; }; | |
| if (yych == 'x') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| case 76: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 77: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 69; continue; }; | |
| if (yych == 's') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 78: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'n') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 79: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'e') { gotoCase = 89; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 80: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'r') { gotoCase = 87; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 81: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'u') { gotoCase = 85; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 82: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'z') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 83: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'H') { gotoCase = 68; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'z') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 85: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'r') { gotoCase = 68; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'n') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 87: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'a') { gotoCase = 68; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'd') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 89: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'g') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 90: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'q') { gotoCase = 68; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych != 'e') { gotoCase = 68; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 93: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'd') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 94: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 69; continue; }; | |
| { gotoCase = 68; continue; }; | |
| case 95: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'r') { gotoCase = 51; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'n') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 97: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'd') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 98: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 99: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'z') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 100: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'a') { gotoCase = 51; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'd') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 102: | |
| yych = this._charAt(++cursor); | |
| if (yych == 'g') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 103: | |
| yych = this._charAt(++cursor); | |
| if (yych != 'q') { gotoCase = 51; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych != 'e') { gotoCase = 51; continue; }; | |
| yych = this._charAt(++cursor); | |
| if (yych == 'm') { gotoCase = 65; continue; }; | |
| { gotoCase = 51; continue; }; | |
| case 106: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 110; continue; }; | |
| { gotoCase = 106; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 110; continue; }; | |
| if (yych != '*') { gotoCase = 106; continue; }; | |
| } | |
| case 108: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych == '*') { gotoCase = 108; continue; }; | |
| if (yych == '/') { gotoCase = 112; continue; }; | |
| { gotoCase = 106; continue; }; | |
| case 110: | |
| ++cursor; | |
| this.setLexCondition(this._lexConditions.COMMENT); | |
| { this.tokenType = "css-comment"; return cursor; } | |
| case 112: | |
| ++cursor; | |
| { this.tokenType = "css-comment"; return cursor; } | |
| case 114: | |
| yyaccept = 0; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '.') { | |
| if (yych <= '"') { | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 32; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 32; continue; }; | |
| if (yych <= ' ') { gotoCase = 118; continue; }; | |
| { gotoCase = 114; continue; }; | |
| } | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '%') { gotoCase = 118; continue; }; | |
| if (yych <= '&') { gotoCase = 114; continue; }; | |
| } else { | |
| if (yych == '-') { gotoCase = 114; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych <= '=') { | |
| if (yych <= '9') { gotoCase = 114; continue; }; | |
| if (yych <= '<') { gotoCase = 118; continue; }; | |
| { gotoCase = 114; continue; }; | |
| } else { | |
| if (yych <= '?') { gotoCase = 118; continue; }; | |
| if (yych <= '[') { gotoCase = 114; continue; }; | |
| { gotoCase = 120; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych == '^') { gotoCase = 118; continue; }; | |
| { gotoCase = 114; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 118; continue; }; | |
| if (yych <= 'z') { gotoCase = 114; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } | |
| } | |
| } | |
| case 116: | |
| ++cursor; | |
| if ((yych = this._charAt(cursor)) <= '<') { | |
| if (yych <= '\'') { | |
| if (yych <= ' ') { gotoCase = 117; continue; }; | |
| if (yych <= '"') { gotoCase = 50; continue; }; | |
| if (yych >= '&') { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '-') { | |
| if (yych >= '-') { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '.') { gotoCase = 117; continue; }; | |
| if (yych <= '9') { gotoCase = 50; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= ']') { | |
| if (yych <= '?') { | |
| if (yych <= '=') { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych != '\\') { gotoCase = 50; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych >= '_') { gotoCase = 50; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 117; continue; }; | |
| if (yych <= 'z') { gotoCase = 50; continue; }; | |
| } | |
| } | |
| } | |
| case 117: | |
| { return this._stringToken(cursor, true); } | |
| case 118: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '\r') { | |
| if (yych == '\n') { gotoCase = 68; continue; }; | |
| if (yych <= '\f') { gotoCase = 118; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '&') { gotoCase = 118; continue; }; | |
| { gotoCase = 123; continue; }; | |
| } else { | |
| if (yych != '\\') { gotoCase = 118; continue; }; | |
| } | |
| } | |
| case 120: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= 'a') { | |
| if (yych <= '!') { | |
| if (yych <= '\n') { | |
| if (yych <= '\t') { gotoCase = 68; continue; }; | |
| } else { | |
| if (yych != '\r') { gotoCase = 68; continue; }; | |
| } | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '"') { gotoCase = 118; continue; }; | |
| if (yych <= '&') { gotoCase = 68; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 118; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'q') { | |
| if (yych <= 'f') { | |
| if (yych <= 'b') { gotoCase = 118; continue; }; | |
| if (yych <= 'e') { gotoCase = 68; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } else { | |
| if (yych == 'n') { gotoCase = 118; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| } else { | |
| if (yych <= 't') { | |
| if (yych == 's') { gotoCase = 68; continue; }; | |
| { gotoCase = 118; continue; }; | |
| } else { | |
| if (yych == 'v') { gotoCase = 118; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| } | |
| } | |
| ++cursor; | |
| this.setLexCondition(this._lexConditions.SSTRING); | |
| { return this._stringToken(cursor); } | |
| case 123: | |
| yych = this._charAt(++cursor); | |
| { gotoCase = 117; continue; }; | |
| case 124: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '<') { | |
| if (yych <= '\'') { | |
| if (yych <= ' ') { gotoCase = 126; continue; }; | |
| if (yych <= '"') { gotoCase = 124; continue; }; | |
| if (yych >= '&') { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych <= '-') { | |
| if (yych >= '-') { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych <= '.') { gotoCase = 126; continue; }; | |
| if (yych <= '9') { gotoCase = 124; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= ']') { | |
| if (yych <= '?') { | |
| if (yych <= '=') { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych != '\\') { gotoCase = 124; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych >= '_') { gotoCase = 124; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 126; continue; }; | |
| if (yych <= 'z') { gotoCase = 124; continue; }; | |
| } | |
| } | |
| } | |
| case 126: | |
| { | |
| if (this._condition.parseCondition === this._condition.parseCondition.INITIAL || this._condition.parseCondition === this._condition.parseCondition.AT_RULE) | |
| this._setParseCondition(this._parseConditions.PROPERTY); | |
| this.tokenType = "scss-variable"; | |
| return cursor; | |
| } | |
| case 127: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '@') { | |
| if (yych <= '/') { gotoCase = 129; continue; }; | |
| if (yych <= '9') { gotoCase = 127; continue; }; | |
| } else { | |
| if (yych <= 'Z') { gotoCase = 127; continue; }; | |
| if (yych <= '`') { gotoCase = 129; continue; }; | |
| if (yych <= 'z') { gotoCase = 127; continue; }; | |
| } | |
| case 129: | |
| { | |
| if (this._isPropertyValue()) | |
| this.tokenType = "css-color"; | |
| else if (this._condition.parseCondition === this._parseConditions.INITIAL) | |
| this.tokenType = "css-selector"; | |
| else | |
| this.tokenType = null; | |
| return cursor; | |
| } | |
| case 130: | |
| yyaccept = 0; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '.') { | |
| if (yych <= '!') { | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 32; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 32; continue; }; | |
| if (yych >= '!') { gotoCase = 130; continue; }; | |
| } | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '"') { gotoCase = 116; continue; }; | |
| if (yych >= '&') { gotoCase = 130; continue; }; | |
| } else { | |
| if (yych == '-') { gotoCase = 130; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych <= '=') { | |
| if (yych <= '9') { gotoCase = 130; continue; }; | |
| if (yych >= '=') { gotoCase = 130; continue; }; | |
| } else { | |
| if (yych <= '?') { gotoCase = 132; continue; }; | |
| if (yych <= '[') { gotoCase = 130; continue; }; | |
| { gotoCase = 134; continue; }; | |
| } | |
| } else { | |
| if (yych <= '_') { | |
| if (yych != '^') { gotoCase = 130; continue; }; | |
| } else { | |
| if (yych <= '`') { gotoCase = 132; continue; }; | |
| if (yych <= 'z') { gotoCase = 130; continue; }; | |
| } | |
| } | |
| } | |
| case 132: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= '\r') { | |
| if (yych == '\n') { gotoCase = 68; continue; }; | |
| if (yych <= '\f') { gotoCase = 132; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } else { | |
| if (yych <= '"') { | |
| if (yych <= '!') { gotoCase = 132; continue; }; | |
| { gotoCase = 123; continue; }; | |
| } else { | |
| if (yych != '\\') { gotoCase = 132; continue; }; | |
| } | |
| } | |
| case 134: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= 'a') { | |
| if (yych <= '!') { | |
| if (yych <= '\n') { | |
| if (yych <= '\t') { gotoCase = 68; continue; }; | |
| } else { | |
| if (yych != '\r') { gotoCase = 68; continue; }; | |
| } | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '"') { gotoCase = 132; continue; }; | |
| if (yych <= '&') { gotoCase = 68; continue; }; | |
| { gotoCase = 132; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 132; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'q') { | |
| if (yych <= 'f') { | |
| if (yych <= 'b') { gotoCase = 132; continue; }; | |
| if (yych <= 'e') { gotoCase = 68; continue; }; | |
| { gotoCase = 132; continue; }; | |
| } else { | |
| if (yych == 'n') { gotoCase = 132; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| } else { | |
| if (yych <= 't') { | |
| if (yych == 's') { gotoCase = 68; continue; }; | |
| { gotoCase = 132; continue; }; | |
| } else { | |
| if (yych == 'v') { gotoCase = 132; continue; }; | |
| { gotoCase = 68; continue; }; | |
| } | |
| } | |
| } | |
| ++cursor; | |
| this.setLexCondition(this._lexConditions.DSTRING); | |
| { return this._stringToken(cursor); } | |
| case this.case_SSTRING: | |
| yych = this._charAt(cursor); | |
| if (yych <= '\r') { | |
| if (yych == '\n') { gotoCase = 141; continue; }; | |
| if (yych <= '\f') { gotoCase = 140; continue; }; | |
| { gotoCase = 141; continue; }; | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '&') { gotoCase = 140; continue; }; | |
| { gotoCase = 143; continue; }; | |
| } else { | |
| if (yych == '\\') { gotoCase = 145; continue; }; | |
| { gotoCase = 140; continue; }; | |
| } | |
| } | |
| case 139: | |
| { return this._stringToken(cursor); } | |
| case 140: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| { gotoCase = 147; continue; }; | |
| case 141: | |
| ++cursor; | |
| case 142: | |
| { this.tokenType = null; return cursor; } | |
| case 143: | |
| ++cursor; | |
| case 144: | |
| this.setLexCondition(this._lexConditions.INITIAL); | |
| { return this._stringToken(cursor, true); } | |
| case 145: | |
| yych = this._charAt(++cursor); | |
| if (yych <= 'e') { | |
| if (yych <= '\'') { | |
| if (yych == '"') { gotoCase = 146; continue; }; | |
| if (yych <= '&') { gotoCase = 142; continue; }; | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych <= '[') { gotoCase = 142; continue; }; | |
| } else { | |
| if (yych != 'b') { gotoCase = 142; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'r') { | |
| if (yych <= 'm') { | |
| if (yych >= 'g') { gotoCase = 142; continue; }; | |
| } else { | |
| if (yych <= 'n') { gotoCase = 146; continue; }; | |
| if (yych <= 'q') { gotoCase = 142; continue; }; | |
| } | |
| } else { | |
| if (yych <= 't') { | |
| if (yych <= 's') { gotoCase = 142; continue; }; | |
| } else { | |
| if (yych != 'v') { gotoCase = 142; continue; }; | |
| } | |
| } | |
| } | |
| case 146: | |
| yyaccept = 0; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| case 147: | |
| if (yych <= '\r') { | |
| if (yych == '\n') { gotoCase = 139; continue; }; | |
| if (yych <= '\f') { gotoCase = 146; continue; }; | |
| { gotoCase = 139; continue; }; | |
| } else { | |
| if (yych <= '\'') { | |
| if (yych <= '&') { gotoCase = 146; continue; }; | |
| { gotoCase = 150; continue; }; | |
| } else { | |
| if (yych != '\\') { gotoCase = 146; continue; }; | |
| } | |
| } | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych <= 'e') { | |
| if (yych <= '\'') { | |
| if (yych == '"') { gotoCase = 146; continue; }; | |
| if (yych >= '\'') { gotoCase = 146; continue; }; | |
| } else { | |
| if (yych <= '\\') { | |
| if (yych >= '\\') { gotoCase = 146; continue; }; | |
| } else { | |
| if (yych == 'b') { gotoCase = 146; continue; }; | |
| } | |
| } | |
| } else { | |
| if (yych <= 'r') { | |
| if (yych <= 'm') { | |
| if (yych <= 'f') { gotoCase = 146; continue; }; | |
| } else { | |
| if (yych <= 'n') { gotoCase = 146; continue; }; | |
| if (yych >= 'r') { gotoCase = 146; continue; }; | |
| } | |
| } else { | |
| if (yych <= 't') { | |
| if (yych >= 't') { gotoCase = 146; continue; }; | |
| } else { | |
| if (yych == 'v') { gotoCase = 146; continue; }; | |
| } | |
| } | |
| } | |
| cursor = YYMARKER; | |
| { gotoCase = 139; continue; }; | |
| case 150: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| { gotoCase = 144; continue; }; | |
| } | |
| } | |
| } | |
| } | |
| WebInspector.SourceCSSTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype; | |
| WebInspector.SourceHTMLTokenizer = function() | |
| { | |
| WebInspector.SourceTokenizer.call(this); | |
| this._lexConditions = { | |
| INITIAL: 0, | |
| COMMENT: 1, | |
| DOCTYPE: 2, | |
| TAG: 3, | |
| DSTRING: 4, | |
| SSTRING: 5 | |
| }; | |
| this.case_INITIAL = 1000; | |
| this.case_COMMENT = 1001; | |
| this.case_DOCTYPE = 1002; | |
| this.case_TAG = 1003; | |
| this.case_DSTRING = 1004; | |
| this.case_SSTRING = 1005; | |
| this._parseConditions = { | |
| INITIAL: 0, | |
| ATTRIBUTE: 1, | |
| ATTRIBUTE_VALUE: 2, | |
| LINKIFY: 4, | |
| A_NODE: 8, | |
| SCRIPT: 16, | |
| STYLE: 32 | |
| }; | |
| this.condition = this.createInitialCondition(); | |
| } | |
| WebInspector.SourceHTMLTokenizer.prototype = { | |
| createInitialCondition: function() | |
| { | |
| return { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL }; | |
| }, | |
| set line(line) { | |
| if (this._condition.internalJavaScriptTokenizerCondition) { | |
| var match = /<\/script/i.exec(line); | |
| if (match) { | |
| this._internalJavaScriptTokenizer.line = line.substring(0, match.index); | |
| } else | |
| this._internalJavaScriptTokenizer.line = line; | |
| } else if (this._condition.internalCSSTokenizerCondition) { | |
| var match = /<\/style/i.exec(line); | |
| if (match) { | |
| this._internalCSSTokenizer.line = line.substring(0, match.index); | |
| } else | |
| this._internalCSSTokenizer.line = line; | |
| } | |
| this._line = line; | |
| }, | |
| _isExpectingAttribute: function() | |
| { | |
| return this._condition.parseCondition & this._parseConditions.ATTRIBUTE; | |
| }, | |
| _isExpectingAttributeValue: function() | |
| { | |
| return this._condition.parseCondition & this._parseConditions.ATTRIBUTE_VALUE; | |
| }, | |
| _setExpectingAttribute: function() | |
| { | |
| if (this._isExpectingAttributeValue()) | |
| this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE_VALUE; | |
| this._condition.parseCondition |= this._parseConditions.ATTRIBUTE; | |
| }, | |
| _setExpectingAttributeValue: function() | |
| { | |
| if (this._isExpectingAttribute()) | |
| this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE; | |
| this._condition.parseCondition |= this._parseConditions.ATTRIBUTE_VALUE; | |
| }, | |
| _stringToken: function(cursor, stringEnds) | |
| { | |
| if (!this._isExpectingAttributeValue()) { | |
| this.tokenType = null; | |
| return cursor; | |
| } | |
| this.tokenType = this._attrValueTokenType(); | |
| if (stringEnds) | |
| this._setExpectingAttribute(); | |
| return cursor; | |
| }, | |
| _attrValueTokenType: function() | |
| { | |
| if (this._condition.parseCondition & this._parseConditions.LINKIFY) { | |
| if (this._condition.parseCondition & this._parseConditions.A_NODE) | |
| return "html-external-link"; | |
| return "html-resource-link"; | |
| } | |
| return "html-attribute-value"; | |
| }, | |
| get _internalJavaScriptTokenizer() | |
| { | |
| return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript"); | |
| }, | |
| get _internalCSSTokenizer() | |
| { | |
| return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css"); | |
| }, | |
| scriptStarted: function(cursor) | |
| { | |
| this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.createInitialCondition(); | |
| }, | |
| scriptEnded: function(cursor) | |
| { | |
| }, | |
| styleSheetStarted: function(cursor) | |
| { | |
| this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.createInitialCondition(); | |
| }, | |
| styleSheetEnded: function(cursor) | |
| { | |
| }, | |
| nextToken: function(cursor) | |
| { | |
| if (this._condition.internalJavaScriptTokenizerCondition) { | |
| this.line = this._line; | |
| if (cursor !== this._internalJavaScriptTokenizer._line.length) { | |
| this._internalJavaScriptTokenizer.condition = this._condition.internalJavaScriptTokenizerCondition; | |
| var result = this._internalJavaScriptTokenizer.nextToken(cursor); | |
| this.tokenType = this._internalJavaScriptTokenizer.tokenType; | |
| this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.condition; | |
| return result; | |
| } else if (cursor !== this._line.length) | |
| delete this._condition.internalJavaScriptTokenizerCondition; | |
| } else if (this._condition.internalCSSTokenizerCondition) { | |
| this.line = this._line; | |
| if (cursor !== this._internalCSSTokenizer._line.length) { | |
| this._internalCSSTokenizer.condition = this._condition.internalCSSTokenizerCondition; | |
| var result = this._internalCSSTokenizer.nextToken(cursor); | |
| this.tokenType = this._internalCSSTokenizer.tokenType; | |
| this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.condition; | |
| return result; | |
| } else if (cursor !== this._line.length) | |
| delete this._condition.internalCSSTokenizerCondition; | |
| } | |
| var cursorOnEnter = cursor; | |
| var gotoCase = 1; | |
| var YYMARKER; | |
| while (1) { | |
| switch (gotoCase) | |
| { | |
| case 1: var yych; | |
| var yyaccept = 0; | |
| if (this.getLexCondition() < 3) { | |
| if (this.getLexCondition() < 1) { | |
| { gotoCase = this.case_INITIAL; continue; }; | |
| } else { | |
| if (this.getLexCondition() < 2) { | |
| { gotoCase = this.case_COMMENT; continue; }; | |
| } else { | |
| { gotoCase = this.case_DOCTYPE; continue; }; | |
| } | |
| } | |
| } else { | |
| if (this.getLexCondition() < 4) { | |
| { gotoCase = this.case_TAG; continue; }; | |
| } else { | |
| if (this.getLexCondition() < 5) { | |
| { gotoCase = this.case_DSTRING; continue; }; | |
| } else { | |
| { gotoCase = this.case_SSTRING; continue; }; | |
| } | |
| } | |
| } | |
| case this.case_COMMENT: | |
| yych = this._charAt(cursor); | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 4; continue; }; | |
| { gotoCase = 3; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 4; continue; }; | |
| if (yych == '-') { gotoCase = 6; continue; }; | |
| { gotoCase = 3; continue; }; | |
| } | |
| case 2: | |
| { this.tokenType = "html-comment"; return cursor; } | |
| case 3: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| { gotoCase = 9; continue; }; | |
| case 4: | |
| ++cursor; | |
| case 5: | |
| { this.tokenType = null; return cursor; } | |
| case 6: | |
| yyaccept = 1; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych != '-') { gotoCase = 5; continue; }; | |
| case 7: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych == '>') { gotoCase = 10; continue; }; | |
| case 8: | |
| yyaccept = 0; | |
| YYMARKER = ++cursor; | |
| yych = this._charAt(cursor); | |
| case 9: | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 2; continue; }; | |
| { gotoCase = 8; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 2; continue; }; | |
| if (yych == '-') { gotoCase = 12; continue; }; | |
| { gotoCase = 8; continue; }; | |
| } | |
| case 10: | |
| ++cursor; | |
| this.setLexCondition(this._lexConditions.INITIAL); | |
| { this.tokenType = "html-comment"; return cursor; } | |
| case 12: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| if (yych == '-') { gotoCase = 7; continue; }; | |
| cursor = YYMARKER; | |
| if (yyaccept <= 0) { | |
| { gotoCase = 2; continue; }; | |
| } else { | |
| { gotoCase = 5; continue; }; | |
| } | |
| case this.case_DOCTYPE: | |
| yych = this._charAt(cursor); | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 18; continue; }; | |
| { gotoCase = 17; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 18; continue; }; | |
| if (yych == '>') { gotoCase = 20; continue; }; | |
| { gotoCase = 17; continue; }; | |
| } | |
| case 16: | |
| { this.tokenType = "html-doctype"; return cursor; } | |
| case 17: | |
| yych = this._charAt(++cursor); | |
| { gotoCase = 23; continue; }; | |
| case 18: | |
| ++cursor; | |
| { this.tokenType = null; return cursor; } | |
| case 20: | |
| ++cursor; | |
| this.setLexCondition(this._lexConditions.INITIAL); | |
| { this.tokenType = "html-doctype"; return cursor; } | |
| case 22: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| case 23: | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 16; continue; }; | |
| { gotoCase = 22; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 16; continue; }; | |
| if (yych == '>') { gotoCase = 16; continue; }; | |
| { gotoCase = 22; continue; }; | |
| } | |
| case this.case_DSTRING: | |
| yych = this._charAt(cursor); | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 28; continue; }; | |
| { gotoCase = 27; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 28; continue; }; | |
| if (yych == '"') { gotoCase = 30; continue; }; | |
| { gotoCase = 27; continue; }; | |
| } | |
| case 26: | |
| { return this._stringToken(cursor); } | |
| case 27: | |
| yych = this._charAt(++cursor); | |
| { gotoCase = 34; continue; }; | |
| case 28: | |
| ++cursor; | |
| { this.tokenType = null; return cursor; } | |
| case 30: | |
| ++cursor; | |
| case 31: | |
| this.setLexCondition(this._lexConditions.TAG); | |
| { return this._stringToken(cursor, true); } | |
| case 32: | |
| yych = this._charAt(++cursor); | |
| { gotoCase = 31; continue; }; | |
| case 33: | |
| ++cursor; | |
| yych = this._charAt(cursor); | |
| case 34: | |
| if (yych <= '\f') { | |
| if (yych == '\n') { gotoCase = 26; continue; }; | |
| { gotoCase = 33; continue; }; | |
| } else { | |
| if (yych <= '\r') { gotoCase = 26; continue; }; | |
| if (yych == '"') { gotoCase = 32; continue; }; | |
| { gotoCase = 33; continue; }; | |
| } | |
| case this.case_INITIAL: | |
| yych = this._charAt(cursor); | |
| if (yych == '<') { gotoCase = 39; continue; }; | |
| ++cursor; | |
| { this.tokenType = null; return cursor; } | |
| case 39: | |
| yyaccept = 0; | |
| yych = this._charAt(YYMARKER = ++cursor); | |
| if (yych <= '/') { | |
| if (yych == '!') { gotoCase = 44; continue; }; | |
| if (yych >= '/') { gotoCase = 41; continue; }; | |
| } else { | |
| if (yych <= 'S') { | |
| if (yych >= 'S') { gotoCase = 42; continue; }; | |
| } else { | |
| if (yych == 's') { gotoCase = 42; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment