| /* |
| * 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. |
| */ |
| |
| /** |
| * @extends {WebInspector.View} |
| * @constructor |
| * @param {WebInspector.ContentProvider} contentProvider |
| */ |
| WebInspector.SourceFrame = function(contentProvider) |
| { |
| WebInspector.View.call(this); |
| this.element.addStyleClass("script-view"); |
| this.element.addStyleClass("fill"); |
| |
| this._url = contentProvider.contentURL(); |
| this._contentProvider = contentProvider; |
| |
| var textEditorDelegate = new WebInspector.TextEditorDelegateForSourceFrame(this); |
| |
| loadScript("CodeMirrorTextEditor.js"); |
| this._textEditor = new WebInspector.CodeMirrorTextEditor(this._url, textEditorDelegate); |
| |
| this._currentSearchResultIndex = -1; |
| this._searchResults = []; |
| |
| this._messages = []; |
| this._rowMessages = {}; |
| this._messageBubbles = {}; |
| |
| this._textEditor.setReadOnly(!this.canEditSource()); |
| |
| this._shortcuts = {}; |
| this.addShortcut(WebInspector.KeyboardShortcut.makeKey("s", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta), this._commitEditing.bind(this)); |
| this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); |
| |
| this._sourcePosition = new WebInspector.StatusBarText("", "source-frame-cursor-position"); |
| } |
| |
| /** |
| * @param {string} query |
| * @param {string=} modifiers |
| * @return {!RegExp} |
| */ |
| WebInspector.SourceFrame.createSearchRegex = function(query, modifiers) |
| { |
| var regex; |
| modifiers = modifiers || ""; |
| |
| // First try creating regex if user knows the / / hint. |
| try { |
| if (/^\/.+\/$/.test(query)) { |
| regex = new RegExp(query.substring(1, query.length - 1), modifiers); |
| regex.__fromRegExpQuery = true; |
| } |
| } catch (e) { |
| // Silent catch. |
| } |
| |
| // Otherwise just do case-insensitive search. |
| if (!regex) |
| regex = createPlainTextSearchRegex(query, "i" + modifiers); |
| |
| return regex; |
| } |
| |
| WebInspector.SourceFrame.Events = { |
| ScrollChanged: "ScrollChanged", |
| SelectionChanged: "SelectionChanged" |
| } |
| |
| WebInspector.SourceFrame.prototype = { |
| /** |
| * @param {number} key |
| * @param {function()} handler |
| */ |
| addShortcut: function(key, handler) |
| { |
| this._shortcuts[key] = handler; |
| }, |
| |
| wasShown: function() |
| { |
| this._ensureContentLoaded(); |
| this._textEditor.show(this.element); |
| this._editorAttached = true; |
| this._wasShownOrLoaded(); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _isEditorShowing: function() |
| { |
| return this.isShowing() && this._editorAttached; |
| }, |
| |
| willHide: function() |
| { |
| WebInspector.View.prototype.willHide.call(this); |
| |
| this._clearPositionHighlight(); |
| this._clearLineToReveal(); |
| }, |
| |
| /** |
| * @return {?Element} |
| */ |
| statusBarText: function() |
| { |
| return this._sourcePosition.element; |
| }, |
| |
| /** |
| * @return {Array.<Element>} |
| */ |
| 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]; |
| var lineNumber = parseInt(line, 10); |
| this._textEditor.removeDecoration(lineNumber, bubble); |
| } |
| |
| this._messages = []; |
| this._rowMessages = {}; |
| this._messageBubbles = {}; |
| }, |
| |
| /** |
| * @override |
| */ |
| canHighlightPosition: function() |
| { |
| return true; |
| }, |
| |
| /** |
| * @override |
| */ |
| highlightPosition: function(line, column) |
| { |
| this._clearLineToReveal(); |
| this._clearLineToScrollTo(); |
| this._clearSelectionToSet(); |
| this._positionToHighlight = { line: line, column: column }; |
| this._innerHighlightPositionIfNeeded(); |
| }, |
| |
| _innerHighlightPositionIfNeeded: function() |
| { |
| if (!this._positionToHighlight) |
| return; |
| |
| if (!this.loaded || !this._isEditorShowing()) |
| return; |
| |
| this._textEditor.highlightPosition(this._positionToHighlight.line, this._positionToHighlight.column); |
| delete this._positionToHighlight; |
| }, |
| |
| _clearPositionHighlight: function() |
| { |
| this._textEditor.clearPositionHighlight(); |
| delete this._positionToHighlight; |
| }, |
| |
| /** |
| * @param {number} line |
| */ |
| revealLine: function(line) |
| { |
| this._clearPositionHighlight(); |
| this._clearLineToScrollTo(); |
| this._clearSelectionToSet(); |
| this._lineToReveal = line; |
| this._innerRevealLineIfNeeded(); |
| }, |
| |
| _innerRevealLineIfNeeded: function() |
| { |
| if (typeof this._lineToReveal === "number") { |
| if (this.loaded && this._isEditorShowing()) { |
| this._textEditor.revealLine(this._lineToReveal); |
| delete this._lineToReveal; |
| } |
| } |
| }, |
| |
| _clearLineToReveal: function() |
| { |
| delete this._lineToReveal; |
| }, |
| |
| /** |
| * @param {number} line |
| */ |
| scrollToLine: function(line) |
| { |
| this._clearPositionHighlight(); |
| this._clearLineToReveal(); |
| this._lineToScrollTo = line; |
| this._innerScrollToLineIfNeeded(); |
| }, |
| |
| _innerScrollToLineIfNeeded: function() |
| { |
| if (typeof this._lineToScrollTo === "number") { |
| if (this.loaded && this._isEditorShowing()) { |
| this._textEditor.scrollToLine(this._lineToScrollTo); |
| delete this._lineToScrollTo; |
| } |
| } |
| }, |
| |
| _clearLineToScrollTo: function() |
| { |
| delete this._lineToScrollTo; |
| }, |
| |
| /** |
| * @param {WebInspector.TextRange} textRange |
| */ |
| setSelection: function(textRange) |
| { |
| this._selectionToSet = textRange; |
| this._innerSetSelectionIfNeeded(); |
| }, |
| |
| _innerSetSelectionIfNeeded: function() |
| { |
| if (this._selectionToSet && this.loaded && this._isEditorShowing()) { |
| this._textEditor.setSelection(this._selectionToSet); |
| delete this._selectionToSet; |
| } |
| }, |
| |
| _clearSelectionToSet: function() |
| { |
| delete this._selectionToSet; |
| }, |
| |
| _wasShownOrLoaded: function() |
| { |
| this._innerHighlightPositionIfNeeded(); |
| this._innerRevealLineIfNeeded(); |
| this._innerSetSelectionIfNeeded(); |
| this._innerScrollToLineIfNeeded(); |
| }, |
| |
| onTextChanged: function(oldRange, newRange) |
| { |
| if (!this._isReplacing) |
| WebInspector.searchController.cancelSearch(); |
| this.clearMessages(); |
| }, |
| |
| _simplifyMimeType: function(content, mimeType) |
| { |
| if (!mimeType) |
| return ""; |
| if (mimeType.indexOf("javascript") >= 0 || |
| mimeType.indexOf("jscript") >= 0 || |
| mimeType.indexOf("ecmascript") >= 0) |
| return "text/javascript"; |
| // A hack around the fact that files with "php" extension might be either standalone or html embedded php scripts. |
| if (mimeType === "text/x-php" && content.match(/\<\?.*\?\>/g)) |
| return "application/x-httpd-php"; |
| return mimeType; |
| }, |
| |
| /** |
| * @param {string} highlighterType |
| */ |
| setHighlighterType: function(highlighterType) |
| { |
| this._highlighterType = highlighterType; |
| this._updateHighlighterType(""); |
| }, |
| |
| /** |
| * @param {string} content |
| */ |
| _updateHighlighterType: function(content) |
| { |
| this._textEditor.setMimeType(this._simplifyMimeType(content, this._highlighterType)); |
| }, |
| |
| /** |
| * @param {?string} content |
| */ |
| setContent: function(content) |
| { |
| if (!this._loaded) { |
| this._loaded = true; |
| this._textEditor.setText(content || ""); |
| this._textEditor.markClean(); |
| } else { |
| var firstLine = this._textEditor.firstVisibleLine(); |
| var selection = this._textEditor.selection(); |
| this._textEditor.setText(content || ""); |
| this._textEditor.scrollToLine(firstLine); |
| this._textEditor.setSelection(selection); |
| } |
| |
| this._updateHighlighterType(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.endUpdates(); |
| }, |
| |
| /** |
| * @param {string} query |
| * @param {boolean} shouldJump |
| * @param {function(WebInspector.View, number)} callback |
| * @param {function(number)=} currentMatchChangedCallback |
| */ |
| performSearch: function(query, shouldJump, callback, currentMatchChangedCallback) |
| { |
| function doFindSearchMatches(query) |
| { |
| this._currentSearchResultIndex = -1; |
| this._searchResults = []; |
| |
| var regex = WebInspector.SourceFrame.createSearchRegex(query); |
| this._searchRegex = regex; |
| this._searchResults = this._collectRegexMatches(regex); |
| if (!this._searchResults.length) |
| this._textEditor.cancelSearchResultsHighlight(); |
| else if (shouldJump) |
| this.jumpToNextSearchResult(); |
| else |
| this._textEditor.highlightSearchResults(regex, null); |
| callback(this, this._searchResults.length); |
| } |
| |
| this._resetSearch(); |
| this._currentSearchMatchChangedCallback = currentMatchChangedCallback; |
| if (this.loaded) |
| doFindSearchMatches.call(this, query); |
| else |
| this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query); |
| |
| this._ensureContentLoaded(); |
| }, |
| |
| _editorFocused: function() |
| { |
| if (!this._searchResults.length) |
| return; |
| this._currentSearchResultIndex = -1; |
| if (this._currentSearchMatchChangedCallback) |
| this._currentSearchMatchChangedCallback(this._currentSearchResultIndex); |
| this._textEditor.highlightSearchResults(this._searchRegex, null); |
| }, |
| |
| _searchResultAfterSelectionIndex: function(selection) |
| { |
| if (!selection) |
| return 0; |
| for (var i = 0; i < this._searchResults.length; ++i) { |
| if (this._searchResults[i].compareTo(selection) >= 0) |
| return i; |
| } |
| return 0; |
| }, |
| |
| _resetSearch: function() |
| { |
| delete this._delayedFindSearchMatches; |
| delete this._currentSearchMatchChangedCallback; |
| this._currentSearchResultIndex = -1; |
| this._searchResults = []; |
| delete this._searchRegex; |
| }, |
| |
| searchCanceled: function() |
| { |
| var range = this._currentSearchResultIndex !== -1 ? this._searchResults[this._currentSearchResultIndex] : null; |
| this._resetSearch(); |
| if (!this.loaded) |
| return; |
| this._textEditor.cancelSearchResultsHighlight(); |
| if (range) |
| this._textEditor.setSelection(range); |
| }, |
| |
| hasSearchResults: function() |
| { |
| return this._searchResults.length > 0; |
| }, |
| |
| jumpToFirstSearchResult: function() |
| { |
| this.jumpToSearchResult(0); |
| }, |
| |
| jumpToLastSearchResult: function() |
| { |
| this.jumpToSearchResult(this._searchResults.length - 1); |
| }, |
| |
| jumpToNextSearchResult: function() |
| { |
| var currentIndex = this._searchResultAfterSelectionIndex(this._textEditor.selection()); |
| var nextIndex = this._currentSearchResultIndex === -1 ? currentIndex : currentIndex + 1; |
| this.jumpToSearchResult(nextIndex); |
| }, |
| |
| jumpToPreviousSearchResult: function() |
| { |
| var currentIndex = this._searchResultAfterSelectionIndex(this._textEditor.selection()); |
| this.jumpToSearchResult(currentIndex - 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; |
| if (this._currentSearchMatchChangedCallback) |
| this._currentSearchMatchChangedCallback(this._currentSearchResultIndex); |
| this._textEditor.highlightSearchResults(this._searchRegex, this._searchResults[this._currentSearchResultIndex]); |
| }, |
| |
| /** |
| * @param {string} text |
| */ |
| replaceSearchMatchWith: function(text) |
| { |
| var range = this._searchResults[this._currentSearchResultIndex]; |
| if (!range) |
| return; |
| this._textEditor.highlightSearchResults(this._searchRegex, null); |
| |
| this._isReplacing = true; |
| var newRange = this._textEditor.editRange(range, text); |
| delete this._isReplacing; |
| |
| this._textEditor.setSelection(newRange.collapseToEnd()); |
| }, |
| |
| /** |
| * @param {string} query |
| * @param {string} replacement |
| */ |
| replaceAllWith: function(query, replacement) |
| { |
| this._textEditor.highlightSearchResults(this._searchRegex, null); |
| |
| var text = this._textEditor.text(); |
| var range = this._textEditor.range(); |
| var regex = WebInspector.SourceFrame.createSearchRegex(query, "g"); |
| if (regex.__fromRegExpQuery) |
| text = text.replace(regex, replacement); |
| else |
| text = text.replace(regex, function() { return 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]); |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| * @param {WebInspector.ConsoleMessage} msg |
| */ |
| addMessageToSource: function(lineNumber, msg) |
| { |
| if (lineNumber >= this._textEditor.linesCount) |
| lineNumber = this._textEditor.linesCount - 1; |
| if (lineNumber < 0) |
| lineNumber = 0; |
| |
| 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); |
| |
| this._textEditor.beginUpdates(); |
| var messageBubbleElement = this._messageBubbles[lineNumber]; |
| if (!messageBubbleElement) { |
| messageBubbleElement = document.createElement("div"); |
| messageBubbleElement.className = "webkit-html-message-bubble"; |
| this._messageBubbles[lineNumber] = messageBubbleElement; |
| this._textEditor.addDecoration(lineNumber, messageBubbleElement); |
| } |
| |
| var imageElement = document.createElement("div"); |
| switch (msg.level) { |
| case WebInspector.ConsoleMessage.MessageLevel.Error: |
| messageBubbleElement.addStyleClass("webkit-html-error-message"); |
| imageElement.className = "error-icon-small"; |
| break; |
| case WebInspector.ConsoleMessage.MessageLevel.Warning: |
| messageBubbleElement.addStyleClass("webkit-html-warning-message"); |
| imageElement.className = "warning-icon-small"; |
| break; |
| } |
| |
| var messageLineElement = document.createElement("div"); |
| messageLineElement.className = "webkit-html-message-line"; |
| messageBubbleElement.appendChild(messageLineElement); |
| |
| // Create the image element in the Inspector's document so we can use relative image URLs. |
| messageLineElement.appendChild(imageElement); |
| messageLineElement.appendChild(document.createTextNode(msg.message)); |
| |
| rowMessage.element = messageLineElement; |
| rowMessage.repeatCount = msg.totalRepeatCount; |
| this._updateMessageRepeatCount(rowMessage); |
| this._textEditor.endUpdates(); |
| }, |
| |
| _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); |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| * @param {WebInspector.ConsoleMessage} msg |
| */ |
| 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); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| canEditSource: function() |
| { |
| return false; |
| }, |
| |
| /** |
| * @param {string} text |
| */ |
| commitEditing: function(text) |
| { |
| }, |
| |
| /** |
| * @param {WebInspector.TextRange} textRange |
| */ |
| selectionChanged: function(textRange) |
| { |
| this._updateSourcePosition(textRange); |
| this.dispatchEventToListeners(WebInspector.SourceFrame.Events.SelectionChanged, textRange); |
| WebInspector.notifications.dispatchEventToListeners(WebInspector.SourceFrame.Events.SelectionChanged, textRange); |
| }, |
| |
| /** |
| * @param {WebInspector.TextRange} textRange |
| */ |
| _updateSourcePosition: function(textRange) |
| { |
| if (!textRange) |
| return; |
| |
| if (textRange.isEmpty()) { |
| this._sourcePosition.setText(WebInspector.UIString("Line %d, Column %d", textRange.endLine + 1, textRange.endColumn + 1)); |
| return; |
| } |
| textRange = textRange.normalize(); |
| |
| var selectedText = this._textEditor.copyRange(textRange); |
| if (textRange.startLine === textRange.endLine) |
| this._sourcePosition.setText(WebInspector.UIString("%d characters selected", selectedText.length)); |
| else |
| this._sourcePosition.setText(WebInspector.UIString("%d lines, %d characters selected", textRange.endLine - textRange.startLine + 1, selectedText.length)); |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| */ |
| 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); |
| return true; |
| }, |
| |
| __proto__: WebInspector.View.prototype |
| } |
| |
| |
| /** |
| * @implements {WebInspector.TextEditorDelegate} |
| * @constructor |
| */ |
| WebInspector.TextEditorDelegateForSourceFrame = function(sourceFrame) |
| { |
| this._sourceFrame = sourceFrame; |
| } |
| |
| WebInspector.TextEditorDelegateForSourceFrame.prototype = { |
| onTextChanged: function(oldRange, newRange) |
| { |
| this._sourceFrame.onTextChanged(oldRange, newRange); |
| }, |
| |
| /** |
| * @param {WebInspector.TextRange} textRange |
| */ |
| selectionChanged: function(textRange) |
| { |
| this._sourceFrame.selectionChanged(textRange); |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| */ |
| scrollChanged: function(lineNumber) |
| { |
| this._sourceFrame.scrollChanged(lineNumber); |
| }, |
| |
| editorFocused: function() |
| { |
| this._sourceFrame._editorFocused(); |
| }, |
| |
| populateLineGutterContextMenu: function(contextMenu, lineNumber) |
| { |
| this._sourceFrame.populateLineGutterContextMenu(contextMenu, lineNumber); |
| }, |
| |
| populateTextAreaContextMenu: function(contextMenu, lineNumber) |
| { |
| this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber); |
| }, |
| |
| /** |
| * @param {string} hrefValue |
| * @param {boolean} isExternal |
| * @return {Element} |
| */ |
| createLink: function(hrefValue, isExternal) |
| { |
| var targetLocation = WebInspector.ParsedURL.completeURL(this._sourceFrame._url, hrefValue); |
| return WebInspector.linkifyURLAsNode(targetLocation || hrefValue, hrefValue, undefined, isExternal); |
| }, |
| |
| __proto__: WebInspector.TextEditorDelegate.prototype |
| } |