Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: Source/devtools/front_end/console/ConsoleView.js

Issue 676193002: Navigate between individual search matches in DevTools console (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Joseph Pecoraro 3 * Copyright (C) 2009 Joseph Pecoraro
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 30 matching lines...) Expand all
41 41
42 this._searchableView = new WebInspector.SearchableView(this); 42 this._searchableView = new WebInspector.SearchableView(this);
43 this._searchableView.setMinimalSearchQuerySize(0); 43 this._searchableView.setMinimalSearchQuerySize(0);
44 this._searchableView.show(this.element); 44 this._searchableView.show(this.element);
45 45
46 this._contentsElement = this._searchableView.element; 46 this._contentsElement = this._searchableView.element;
47 this._contentsElement.classList.add("console-view"); 47 this._contentsElement.classList.add("console-view");
48 this._visibleViewMessages = []; 48 this._visibleViewMessages = [];
49 this._urlToMessageCount = {}; 49 this._urlToMessageCount = {};
50 this._hiddenByFilterCount = 0; 50 this._hiddenByFilterCount = 0;
51 this._regexMatchRanges = [];
52
51 53
52 this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIS tring("Clear console log."), "clear-status-bar-item"); 54 this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIS tring("Clear console log."), "clear-status-bar-item");
53 this._clearConsoleButton.addEventListener("click", this._requestClearMessage s, this); 55 this._clearConsoleButton.addEventListener("click", this._requestClearMessage s, this);
54 56
55 this._executionContextSelector = new WebInspector.StatusBarComboBox(this._ex ecutionContextChanged.bind(this), "console-context"); 57 this._executionContextSelector = new WebInspector.StatusBarComboBox(this._ex ecutionContextChanged.bind(this), "console-context");
56 58
57 /** 59 /**
58 * @type {!Map.<!WebInspector.ExecutionContext, !Element>} 60 * @type {!Map.<!WebInspector.ExecutionContext, !Element>}
59 */ 61 */
60 this._optionByExecutionContext = new Map(); 62 this._optionByExecutionContext = new Map();
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 this._currentGroup = this._currentGroup.parentGroup(); 569 this._currentGroup = this._currentGroup.parentGroup();
568 return; 570 return;
569 } 571 }
570 if (!this._currentGroup.messagesHidden()) { 572 if (!this._currentGroup.messagesHidden()) {
571 var originatingMessage = viewMessage.consoleMessage().originatingMes sage(); 573 var originatingMessage = viewMessage.consoleMessage().originatingMes sage();
572 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage) 574 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage)
573 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result"); 575 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result");
574 576
575 this._visibleViewMessages.push(viewMessage); 577 this._visibleViewMessages.push(viewMessage);
576 578
577 if (this._searchRegex && viewMessage.matchesRegex(this._searchRegex) ) { 579 if (this._searchRegex && this._searchMessage(this._visibleViewMessag es.length-1)) {
robwu 2014/10/25 23:12:59 Spaces around minus.
aknudsen 2014/10/26 11:22:40 Done.
578 this._searchResults.push(viewMessage); 580 this._searchableView.updateSearchMatchesCount(this._regexMatchRa nges.length);
579 this._searchableView.updateSearchMatchesCount(this._searchResult s.length);
580 } 581 }
581 } 582 }
582 583
583 if (viewMessage.consoleMessage().isGroupStartMessage()) 584 if (viewMessage.consoleMessage().isGroupStartMessage())
584 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage); 585 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage);
585 }, 586 },
586 587
587 /** 588 /**
588 * @param {!WebInspector.ConsoleMessage} message 589 * @param {!WebInspector.ConsoleMessage} message
589 * @return {!WebInspector.ConsoleViewMessage} 590 * @return {!WebInspector.ConsoleViewMessage}
590 */ 591 */
591 _createViewMessage: function(message) 592 _createViewMessage: function(message)
592 { 593 {
593 var nestingLevel = this._currentGroup.nestingLevel(); 594 var nestingLevel = this._currentGroup.nestingLevel();
594 switch (message.type) { 595 switch (message.type) {
595 case WebInspector.ConsoleMessage.MessageType.Command: 596 case WebInspector.ConsoleMessage.MessageType.Command:
596 return new WebInspector.ConsoleCommand(message, this._linkifier, nes tingLevel); 597 return new WebInspector.ConsoleCommand(message, this._linkifier, nes tingLevel);
597 case WebInspector.ConsoleMessage.MessageType.Result: 598 case WebInspector.ConsoleMessage.MessageType.Result:
598 return new WebInspector.ConsoleCommandResult(message, this._linkifie r, nestingLevel); 599 return new WebInspector.ConsoleCommandResult(message, this._linkifie r, nestingLevel);
599 case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed: 600 case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed:
600 case WebInspector.ConsoleMessage.MessageType.StartGroup: 601 case WebInspector.ConsoleMessage.MessageType.StartGroup:
601 return new WebInspector.ConsoleGroupViewMessage(message, this._linki fier, nestingLevel); 602 return new WebInspector.ConsoleGroupViewMessage(message, this._linki fier, nestingLevel);
602 default: 603 default:
603 return new WebInspector.ConsoleViewMessage(message, this._linkifier, nestingLevel); 604 return new WebInspector.ConsoleViewMessage(message, this._linkifier, nestingLevel);
604 } 605 }
605 }, 606 },
606 607
607 _consoleCleared: function() 608 _consoleCleared: function()
608 { 609 {
609 this._clearCurrentSearchResultHighlight(); 610 this._clearSearchResultHighlights();
610 this._consoleMessages = []; 611 this._consoleMessages = [];
611 this._updateMessageList(); 612 this._updateMessageList();
612 613
613 if (this._searchRegex) 614 if (this._searchRegex)
614 this._searchableView.updateSearchMatchesCount(0); 615 this._searchableView.updateSearchMatchesCount(0);
615 616
616 this._linkifier.reset(); 617 this._linkifier.reset();
617 }, 618 },
618 619
619 _handleContextMenuEvent: function(event) 620 _handleContextMenuEvent: function(event)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 return true; 678 return true;
678 } 679 }
679 680
680 return false; 681 return false;
681 }, 682 },
682 683
683 _updateMessageList: function() 684 _updateMessageList: function()
684 { 685 {
685 this._topGroup = WebInspector.ConsoleGroup.createTopGroup(); 686 this._topGroup = WebInspector.ConsoleGroup.createTopGroup();
686 this._currentGroup = this._topGroup; 687 this._currentGroup = this._topGroup;
687 this._searchResults = []; 688 this._regexMatchRanges = [];
688 this._hiddenByFilterCount = 0; 689 this._hiddenByFilterCount = 0;
689 for (var i = 0; i < this._visibleViewMessages.length; ++i) { 690 for (var i = 0; i < this._visibleViewMessages.length; ++i) {
690 this._visibleViewMessages[i].resetCloseGroupDecorationCount(); 691 this._visibleViewMessages[i].resetCloseGroupDecorationCount();
691 this._visibleViewMessages[i].resetIncrementRepeatCount(); 692 this._visibleViewMessages[i].resetIncrementRepeatCount();
692 } 693 }
693 this._visibleViewMessages = []; 694 this._visibleViewMessages = [];
694 for (var i = 0; i < this._consoleMessages.length; ++i) 695 for (var i = 0; i < this._consoleMessages.length; ++i)
695 this._appendMessageToEnd(this._consoleMessages[i]); 696 this._appendMessageToEnd(this._consoleMessages[i]);
696 this._updateFilterStatus(); 697 this._updateFilterStatus();
697 this._viewport.invalidate(); 698 this._viewport.invalidate();
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 /** 892 /**
892 * @return {!Array.<!Element>} 893 * @return {!Array.<!Element>}
893 */ 894 */
894 elementsToRestoreScrollPositionsFor: function() 895 elementsToRestoreScrollPositionsFor: function()
895 { 896 {
896 return [this._messagesElement]; 897 return [this._messagesElement];
897 }, 898 },
898 899
899 searchCanceled: function() 900 searchCanceled: function()
900 { 901 {
901 this._clearCurrentSearchResultHighlight(); 902 this._clearSearchResultHighlights();
902 delete this._searchResults; 903 this._regexMatchRanges = [];
903 delete this._searchRegex; 904 delete this._searchRegex;
904 this._viewport.refresh(); 905 this._viewport.refresh();
905 }, 906 },
906 907
907 /** 908 /**
908 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig 909 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
909 * @param {boolean} shouldJump 910 * @param {boolean} shouldJump
910 * @param {boolean=} jumpBackwards 911 * @param {boolean=} jumpBackwards
911 */ 912 */
912 performSearch: function(searchConfig, shouldJump, jumpBackwards) 913 performSearch: function(searchConfig, shouldJump, jumpBackwards)
913 { 914 {
914 var query = searchConfig.query; 915 var query = searchConfig.query;
915 this.searchCanceled(); 916 this.searchCanceled();
916 this._searchableView.updateSearchMatchesCount(0); 917 this._searchableView.updateSearchMatchesCount(0);
917 this._searchRegex = createPlainTextSearchRegex(query, "gi"); 918 this._searchRegex = createPlainTextSearchRegex(query, "gi");
918 919
919 /** @type {!Array.<number>} */ 920 this._regexMatchRanges = [];
920 this._searchResults = []; 921 this._currentMatchRangeIndex = -1;
921 for (var i = 0; i < this._visibleViewMessages.length; i++) { 922 for (var i = 0; i < this._visibleViewMessages.length; i++) {
922 if (this._visibleViewMessages[i].matchesRegex(this._searchRegex)) 923 this._searchMessage(i);
923 this._searchResults.push(i);
924 } 924 }
robwu 2014/10/25 23:12:59 Omit braces for single-line for/if/if-else blocks
aknudsen 2014/10/26 11:22:40 Done.
925 this._searchableView.updateSearchMatchesCount(this._searchResults.length ); 925 this._searchableView.updateSearchMatchesCount(this._regexMatchRanges.len gth);
926 this._currentSearchResultIndex = -1; 926 if (shouldJump) {
927 if (shouldJump && this._searchResults.length) 927 this._jumpToMatch(jumpBackwards ? -1 : 0);
928 this._jumpToSearchResult(jumpBackwards ? -1 : 0); 928 } else {
929 console.log("Not jumping to current search result");
930 }
929 this._viewport.refresh(); 931 this._viewport.refresh();
930 }, 932 },
931 933
932 jumpToNextSearchResult: function() 934 jumpToNextSearchResult: function()
933 { 935 {
934 if (!this._searchResults || !this._searchResults.length) 936 this._jumpToMatch(this._currentMatchRangeIndex + 1);
935 return;
936 this._jumpToSearchResult(this._currentSearchResultIndex + 1);
937 }, 937 },
938 938
939 jumpToPreviousSearchResult: function() 939 jumpToPreviousSearchResult: function()
940 { 940 {
941 if (!this._searchResults || !this._searchResults.length) 941 this._jumpToMatch(this._currentMatchRangeIndex - 1);
942 return;
943 this._jumpToSearchResult(this._currentSearchResultIndex - 1);
944 }, 942 },
945 943
946 /** 944 /**
947 * @return {boolean} 945 * @return {boolean}
948 */ 946 */
949 supportsCaseSensitiveSearch: function() 947 supportsCaseSensitiveSearch: function()
950 { 948 {
951 return false; 949 return false;
952 }, 950 },
953 951
954 /** 952 /**
955 * @return {boolean} 953 * @return {boolean}
956 */ 954 */
957 supportsRegexSearch: function() 955 supportsRegexSearch: function()
958 { 956 {
959 return false; 957 return false;
960 }, 958 },
961 959
962 _clearCurrentSearchResultHighlight: function() 960 _clearSearchResultHighlights: function()
963 { 961 {
964 if (!this._searchResults) 962 console.log("Clearing search result highlights");
965 return; 963 for (var i = 0; i < this._regexMatchRanges.length; ++i) {
966 964 var matchRange = this._regexMatchRanges[i];
967 var highlightedViewMessage = this._visibleViewMessages[this._searchResul ts[this._currentSearchResultIndex]]; 965 var message = this._visibleViewMessages[
968 if (highlightedViewMessage) 966 matchRange.message];
robwu 2014/10/25 23:13:00 matchRange.message? As said in the comment below,
aknudsen 2014/10/26 11:22:40 I changed it to messageIndex, since it's actually
969 highlightedViewMessage.clearHighlight(); 967 if (message) {
970 this._currentSearchResultIndex = -1; 968 message.clearHighlights();
969 }
970 }
971 this._currentMatchRangeIndex = -1;
971 }, 972 },
972 973
973 _jumpToSearchResult: function(index) 974 _jumpToMatch: function(index)
robwu 2014/10/25 23:12:59 "_jumpToSearchResult" was more descriptive than "_
aknudsen 2014/10/26 11:22:40 The reason I renamed to jumpToMatch was to tie int
974 { 975 {
975 index = mod(index, this._searchResults.length); 976 if (!this._regexMatchRanges.length) {
976 this._clearCurrentSearchResultHighlight(); 977 return;
977 this._currentSearchResultIndex = index; 978 }
978 this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIn dex); 979
979 var currentViewMessageIndex = this._searchResults[index]; 980 index = mod(index, this._regexMatchRanges.length);
980 this._viewport.scrollItemIntoView(currentViewMessageIndex); 981 console.log("Jumping to search match #" + index);
981 this._visibleViewMessages[currentViewMessageIndex].highlightSearchResult s(this._searchRegex); 982 var matchRange;
983 var message;
984 if (this._currentMatchRangeIndex >= 0) {
985 // Unmark current match range
986 matchRange = this._regexMatchRanges[this._currentMatchRangeIndex];
987 console.log("Unmarking current search match, in message #" + matchRa nge.message);
988 message = this._visibleViewMessages[matchRange.message];
989 message.highlightMatch(matchRange.start, matchRange.end);
990 }
991
992 this._currentMatchRangeIndex = index;
993 this._searchableView.updateCurrentMatchIndex(index);
994 matchRange = this._regexMatchRanges[index];
995 message = this._visibleViewMessages[matchRange.message];
996 this._viewport.scrollItemIntoView(message);
997 console.log("Highlighting range " + matchRange.start + "," + matchRange. end + " in message #" +
998 matchRange.message + " as the current match");
999 message.highlightMatch(matchRange.start, matchRange.end, true);
1000 },
1001
1002 _searchMessage: function(index)
1003 {
1004 // Reset regex wrt. global search
1005 this._searchRegex.lastIndex = 0;
1006
1007 var numMatches = 0;
1008 var message = this._visibleViewMessages[index];
1009 var text = message.getText();
1010 var match = this._searchRegex.exec(text);
1011 while (match && match[0]) {
robwu 2014/10/25 23:12:59 The idiomatic way to use .exec in a JS loop is: v
aknudsen 2014/10/26 11:22:40 Done.
1012 var matchRange = {
1013 message: index,
robwu 2014/10/25 23:12:59 "message" is confusing. I thought that it was a st
aknudsen 2014/10/26 11:22:40 Done.
1014 start: match.index,
1015 end: match.index + match[0].length-1,
robwu 2014/10/25 23:12:59 Spaces around the minus sign.
aknudsen 2014/10/26 11:22:40 Done.
1016 };
1017 this._regexMatchRanges.push(matchRange);
1018 message.highlightMatch(matchRange.start, matchRange.end);
1019
1020 match = this._searchRegex.exec(text);
1021 ++numMatches;
1022 }
1023
1024 return numMatches > 0;
robwu 2014/10/25 23:12:59 numMatches can be eliminated by using the fact tha
aknudsen 2014/10/26 11:22:40 Done.
982 }, 1025 },
983 1026
984 __proto__: WebInspector.VBox.prototype 1027 __proto__: WebInspector.VBox.prototype
985 } 1028 }
986 1029
987 /** 1030 /**
988 * @constructor 1031 * @constructor
989 * @extends {WebInspector.Object} 1032 * @extends {WebInspector.Object}
990 * @param {!WebInspector.ConsoleView} view 1033 * @param {!WebInspector.ConsoleView} view
991 */ 1034 */
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 * @param {!WebInspector.ConsoleMessage} message 1168 * @param {!WebInspector.ConsoleMessage} message
1126 * @param {!WebInspector.Linkifier} linkifier 1169 * @param {!WebInspector.Linkifier} linkifier
1127 * @param {number} nestingLevel 1170 * @param {number} nestingLevel
1128 */ 1171 */
1129 WebInspector.ConsoleCommand = function(message, linkifier, nestingLevel) 1172 WebInspector.ConsoleCommand = function(message, linkifier, nestingLevel)
1130 { 1173 {
1131 WebInspector.ConsoleViewMessage.call(this, message, linkifier, nestingLevel) ; 1174 WebInspector.ConsoleViewMessage.call(this, message, linkifier, nestingLevel) ;
1132 } 1175 }
1133 1176
1134 WebInspector.ConsoleCommand.prototype = { 1177 WebInspector.ConsoleCommand.prototype = {
1135 clearHighlight: function() 1178 clearHighlights: function()
1136 { 1179 {
1137 var highlightedMessage = this._formattedCommand; 1180 var highlightedMessage = this._formattedCommand;
1138 delete this._formattedCommand; 1181 delete this._formattedCommand;
1139 this._formatCommand(); 1182 this._formatCommand();
1140 this._element.replaceChild(this._formattedCommand, highlightedMessage); 1183 this._element.replaceChild(this._formattedCommand, highlightedMessage);
1141 }, 1184 },
1142 1185
1143 /** 1186 /**
1144 * @param {!RegExp} regexObject 1187 * @param {!RegExp} regexObject
1145 */ 1188 */
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 } 1223 }
1181 return this._element; 1224 return this._element;
1182 }, 1225 },
1183 1226
1184 _formatCommand: function() 1227 _formatCommand: function()
1185 { 1228 {
1186 this._formattedCommand = createElementWithClass("span", "console-message -text source-code"); 1229 this._formattedCommand = createElementWithClass("span", "console-message -text source-code");
1187 this._formattedCommand.textContent = this.text; 1230 this._formattedCommand.textContent = this.text;
1188 }, 1231 },
1189 1232
1233 /**
1234 * @return {!string}
1235 */
1236 getText: function()
1237 {
1238 return this.text;
1239 },
1240
1241 highlightMatch: function(start, end, isCurrent)
1242 {
1243 console.log("Highlighting from position " + start + " to " + end);
1244 WebInspector.highlightSearchResults(this._formattedCommand,
1245 [new WebInspector.SourceRange(start, end - start + 1)], undefined, is Current);
1246 this._element.scrollIntoViewIfNeeded();
1247 },
1248
1190 __proto__: WebInspector.ConsoleViewMessage.prototype 1249 __proto__: WebInspector.ConsoleViewMessage.prototype
1191 } 1250 }
1192 1251
1193 /** 1252 /**
1194 * @constructor 1253 * @constructor
1195 * @extends {WebInspector.ConsoleViewMessage} 1254 * @extends {WebInspector.ConsoleViewMessage}
1196 * @param {!WebInspector.ConsoleMessage} message 1255 * @param {!WebInspector.ConsoleMessage} message
1197 * @param {!WebInspector.Linkifier} linkifier 1256 * @param {!WebInspector.Linkifier} linkifier
1198 * @param {number} nestingLevel 1257 * @param {number} nestingLevel
1199 */ 1258 */
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1284 WebInspector.ConsoleView.ShowConsoleActionDelegate.prototype = { 1343 WebInspector.ConsoleView.ShowConsoleActionDelegate.prototype = {
1285 /** 1344 /**
1286 * @return {boolean} 1345 * @return {boolean}
1287 */ 1346 */
1288 handleAction: function() 1347 handleAction: function()
1289 { 1348 {
1290 WebInspector.console.show(); 1349 WebInspector.console.show();
1291 return true; 1350 return true;
1292 } 1351 }
1293 } 1352 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698