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

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: Synchronize with origin Created 5 years, 11 months 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 this._searchableView = new WebInspector.SearchableView(this); 43 this._searchableView = new WebInspector.SearchableView(this);
44 this._searchableView.setMinimalSearchQuerySize(0); 44 this._searchableView.setMinimalSearchQuerySize(0);
45 this._searchableView.show(this.element); 45 this._searchableView.show(this.element);
46 46
47 this._contentsElement = this._searchableView.element; 47 this._contentsElement = this._searchableView.element;
48 this._contentsElement.classList.add("console-view"); 48 this._contentsElement.classList.add("console-view");
49 this._visibleViewMessages = []; 49 this._visibleViewMessages = [];
50 this._urlToMessageCount = {}; 50 this._urlToMessageCount = {};
51 this._hiddenByFilterCount = 0; 51 this._hiddenByFilterCount = 0;
52 52
53 /**
54 * @type {!Array.<!WebInspector.ConsoleView.RegexMatchRange>}
55 */
56 this._regexMatchRanges = [];
57
53 this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIS tring("Clear console log."), "clear-status-bar-item"); 58 this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIS tring("Clear console log."), "clear-status-bar-item");
54 this._clearConsoleButton.addEventListener("click", this._requestClearMessage s, this); 59 this._clearConsoleButton.addEventListener("click", this._requestClearMessage s, this);
55 60
56 this._executionContextSelector = new WebInspector.StatusBarComboBox(this._ex ecutionContextChanged.bind(this), "console-context"); 61 this._executionContextSelector = new WebInspector.StatusBarComboBox(this._ex ecutionContextChanged.bind(this), "console-context");
57 62
58 /** 63 /**
59 * @type {!Map.<!WebInspector.ExecutionContext, !Element>} 64 * @type {!Map.<!WebInspector.ExecutionContext, !Element>}
60 */ 65 */
61 this._optionByExecutionContext = new Map(); 66 this._optionByExecutionContext = new Map();
62 67
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 this._currentGroup = this._currentGroup.parentGroup(); 586 this._currentGroup = this._currentGroup.parentGroup();
582 return; 587 return;
583 } 588 }
584 if (!this._currentGroup.messagesHidden()) { 589 if (!this._currentGroup.messagesHidden()) {
585 var originatingMessage = viewMessage.consoleMessage().originatingMes sage(); 590 var originatingMessage = viewMessage.consoleMessage().originatingMes sage();
586 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage) 591 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage)
587 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result"); 592 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result");
588 593
589 this._visibleViewMessages.push(viewMessage); 594 this._visibleViewMessages.push(viewMessage);
590 595
591 if (this._searchRegex && viewMessage.matchesRegex(this._searchRegex) ) { 596 if (this._searchRegex && this._searchMessage(this._visibleViewMessag es.length - 1))
592 this._searchResults.push(viewMessage); 597 this._searchableView.updateSearchMatchesCount(this._regexMatchRa nges.length);
593 this._searchableView.updateSearchMatchesCount(this._searchResult s.length);
594 }
595 } 598 }
596 599
597 if (viewMessage.consoleMessage().isGroupStartMessage()) 600 if (viewMessage.consoleMessage().isGroupStartMessage())
598 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage); 601 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage);
599 }, 602 },
600 603
601 /** 604 /**
602 * @param {!WebInspector.ConsoleMessage} message 605 * @param {!WebInspector.ConsoleMessage} message
603 * @return {!WebInspector.ConsoleViewMessage} 606 * @return {!WebInspector.ConsoleViewMessage}
604 */ 607 */
605 _createViewMessage: function(message) 608 _createViewMessage: function(message)
606 { 609 {
607 var nestingLevel = this._currentGroup.nestingLevel(); 610 var nestingLevel = this._currentGroup.nestingLevel();
608 switch (message.type) { 611 switch (message.type) {
609 case WebInspector.ConsoleMessage.MessageType.Command: 612 case WebInspector.ConsoleMessage.MessageType.Command:
610 return new WebInspector.ConsoleCommand(message, this._linkifier, nes tingLevel); 613 return new WebInspector.ConsoleCommand(message, this._linkifier, nes tingLevel);
611 case WebInspector.ConsoleMessage.MessageType.Result: 614 case WebInspector.ConsoleMessage.MessageType.Result:
612 return new WebInspector.ConsoleCommandResult(message, this._linkifie r, nestingLevel); 615 return new WebInspector.ConsoleCommandResult(message, this._linkifie r, nestingLevel);
613 case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed: 616 case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed:
614 case WebInspector.ConsoleMessage.MessageType.StartGroup: 617 case WebInspector.ConsoleMessage.MessageType.StartGroup:
615 return new WebInspector.ConsoleGroupViewMessage(message, this._linki fier, nestingLevel); 618 return new WebInspector.ConsoleGroupViewMessage(message, this._linki fier, nestingLevel);
616 default: 619 default:
617 return new WebInspector.ConsoleViewMessage(message, this._linkifier, nestingLevel); 620 return new WebInspector.ConsoleViewMessage(message, this._linkifier, nestingLevel);
618 } 621 }
619 }, 622 },
620 623
621 _consoleCleared: function() 624 _consoleCleared: function()
622 { 625 {
623 this._clearCurrentSearchResultHighlight(); 626 this._clearSearchResultHighlights();
624 this._consoleMessages = []; 627 this._consoleMessages = [];
625 this._updateMessageList(); 628 this._updateMessageList();
626 this._hidePromptSuggestBox(); 629 this._hidePromptSuggestBox();
627 630
628 if (this._searchRegex) 631 if (this._searchRegex)
629 this._searchableView.updateSearchMatchesCount(0); 632 this._searchableView.updateSearchMatchesCount(0);
630 633
631 this._linkifier.reset(); 634 this._linkifier.reset();
632 }, 635 },
633 636
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 return true; 695 return true;
693 } 696 }
694 697
695 return false; 698 return false;
696 }, 699 },
697 700
698 _updateMessageList: function() 701 _updateMessageList: function()
699 { 702 {
700 this._topGroup = WebInspector.ConsoleGroup.createTopGroup(); 703 this._topGroup = WebInspector.ConsoleGroup.createTopGroup();
701 this._currentGroup = this._topGroup; 704 this._currentGroup = this._topGroup;
702 this._searchResults = []; 705 this._regexMatchRanges = [];
703 this._hiddenByFilterCount = 0; 706 this._hiddenByFilterCount = 0;
704 for (var i = 0; i < this._visibleViewMessages.length; ++i) { 707 for (var i = 0; i < this._visibleViewMessages.length; ++i) {
705 this._visibleViewMessages[i].resetCloseGroupDecorationCount(); 708 this._visibleViewMessages[i].resetCloseGroupDecorationCount();
706 this._visibleViewMessages[i].resetIncrementRepeatCount(); 709 this._visibleViewMessages[i].resetIncrementRepeatCount();
707 } 710 }
708 this._visibleViewMessages = []; 711 this._visibleViewMessages = [];
709 for (var i = 0; i < this._consoleMessages.length; ++i) 712 for (var i = 0; i < this._consoleMessages.length; ++i)
710 this._appendMessageToEnd(this._consoleMessages[i]); 713 this._appendMessageToEnd(this._consoleMessages[i]);
711 this._updateFilterStatus(); 714 this._updateFilterStatus();
712 this._viewport.invalidate(); 715 this._viewport.invalidate();
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 elementsToRestoreScrollPositionsFor: function() 913 elementsToRestoreScrollPositionsFor: function()
911 { 914 {
912 return [this._messagesElement]; 915 return [this._messagesElement];
913 }, 916 },
914 917
915 /** 918 /**
916 * @override 919 * @override
917 */ 920 */
918 searchCanceled: function() 921 searchCanceled: function()
919 { 922 {
920 this._clearCurrentSearchResultHighlight(); 923 this._clearSearchResultHighlights();
921 delete this._searchResults; 924 this._regexMatchRanges = [];
922 delete this._searchRegex; 925 delete this._searchRegex;
923 this._viewport.refresh(); 926 this._viewport.refresh();
924 }, 927 },
925 928
926 /** 929 /**
927 * @override 930 * @override
928 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig 931 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
929 * @param {boolean} shouldJump 932 * @param {boolean} shouldJump
930 * @param {boolean=} jumpBackwards 933 * @param {boolean=} jumpBackwards
931 */ 934 */
932 performSearch: function(searchConfig, shouldJump, jumpBackwards) 935 performSearch: function(searchConfig, shouldJump, jumpBackwards)
933 { 936 {
934 var query = searchConfig.query; 937 var query = searchConfig.query;
935 this.searchCanceled(); 938 this.searchCanceled();
936 this._searchableView.updateSearchMatchesCount(0); 939 this._searchableView.updateSearchMatchesCount(0);
937 this._searchRegex = createPlainTextSearchRegex(query, "gi"); 940 this._searchRegex = createPlainTextSearchRegex(query, "gi");
938 941
939 /** @type {!Array.<number>} */ 942 this._regexMatchRanges = [];
940 this._searchResults = []; 943 this._currentMatchRangeIndex = -1;
941 for (var i = 0; i < this._visibleViewMessages.length; i++) { 944 for (var i = 0; i < this._visibleViewMessages.length; i++)
942 if (this._visibleViewMessages[i].matchesRegex(this._searchRegex)) 945 this._searchMessage(i);
943 this._searchResults.push(i); 946 this._searchableView.updateSearchMatchesCount(this._regexMatchRanges.len gth);
947 if (shouldJump)
948 this._jumpToMatch(jumpBackwards ? -1 : 0);
949 this._viewport.refresh();
950 },
951
952 /**
953 * @param {number} index
954 * @return {boolean}
955 */
956 _searchMessage: function(index)
957 {
958 // Reset regex wrt. global search.
959 this._searchRegex.lastIndex = 0;
960
961 var message = this._visibleViewMessages[index];
962 var text = message.renderedText();
963 var match;
964 var matchRanges = [];
965 var sourceRanges = [];
966 while ((match = this._searchRegex.exec(text)) && match[0]) {
967 matchRanges.push({
968 messageIndex: index,
969 highlightNode: null,
970 });
971 sourceRanges.push(new WebInspector.SourceRange(match.index, match[0] .length));
944 } 972 }
945 this._searchableView.updateSearchMatchesCount(this._searchResults.length ); 973
946 this._currentSearchResultIndex = -1; 974 var matchRange;
947 if (shouldJump && this._searchResults.length) 975 var highlightNodes = message.highlightMatches(sourceRanges);
948 this._jumpToSearchResult(jumpBackwards ? -1 : 0); 976 for (var i = 0; i < matchRanges.length; ++i) {
949 this._viewport.refresh(); 977 matchRange = matchRanges[i];
978 matchRange.highlightNode = highlightNodes[i];
979 this._regexMatchRanges.push(matchRange);
980 }
981
982 return !!matchRange;
950 }, 983 },
951 984
952 /** 985 /**
953 * @override 986 * @override
954 */ 987 */
955 jumpToNextSearchResult: function() 988 jumpToNextSearchResult: function()
956 { 989 {
957 if (!this._searchResults || !this._searchResults.length) 990 this._jumpToMatch(this._currentMatchRangeIndex + 1);
958 return;
959 this._jumpToSearchResult(this._currentSearchResultIndex + 1);
960 }, 991 },
961 992
962 /** 993 /**
963 * @override 994 * @override
964 */ 995 */
965 jumpToPreviousSearchResult: function() 996 jumpToPreviousSearchResult: function()
966 { 997 {
967 if (!this._searchResults || !this._searchResults.length) 998 this._jumpToMatch(this._currentMatchRangeIndex - 1);
968 return;
969 this._jumpToSearchResult(this._currentSearchResultIndex - 1);
970 }, 999 },
971 1000
972 /** 1001 /**
973 * @override 1002 * @override
974 * @return {boolean} 1003 * @return {boolean}
975 */ 1004 */
976 supportsCaseSensitiveSearch: function() 1005 supportsCaseSensitiveSearch: function()
977 { 1006 {
978 return false; 1007 return false;
979 }, 1008 },
980 1009
981 /** 1010 /**
982 * @override 1011 * @override
983 * @return {boolean} 1012 * @return {boolean}
984 */ 1013 */
985 supportsRegexSearch: function() 1014 supportsRegexSearch: function()
986 { 1015 {
987 return false; 1016 return false;
988 }, 1017 },
989 1018
990 _clearCurrentSearchResultHighlight: function() 1019 _clearSearchResultHighlights: function()
991 { 1020 {
992 if (!this._searchResults) 1021 var handledMessageIndexes = [];
1022 for (var i = 0; i < this._regexMatchRanges.length; ++i) {
1023 var matchRange = this._regexMatchRanges[i];
1024 if (handledMessageIndexes[matchRange.messageIndex])
1025 continue;
1026
1027 var message = this._visibleViewMessages[matchRange.messageIndex];
1028 if (message)
1029 message.clearHighlights();
1030 handledMessageIndexes[matchRange.messageIndex] = true;
1031 }
1032 this._currentMatchRangeIndex = -1;
1033 },
1034
1035 /**
1036 * @param {number} index
1037 */
1038 _jumpToMatch: function(index)
1039 {
1040 if (!this._regexMatchRanges.length)
993 return; 1041 return;
994 1042
995 var highlightedViewMessage = this._visibleViewMessages[this._searchResul ts[this._currentSearchResultIndex]]; 1043 var currentSearchResultClassName = "current-search-result";
996 if (highlightedViewMessage)
997 highlightedViewMessage.clearHighlight();
998 this._currentSearchResultIndex = -1;
999 },
1000 1044
1001 _jumpToSearchResult: function(index) 1045 var matchRange;
1002 { 1046 if (this._currentMatchRangeIndex >= 0) {
1003 index = mod(index, this._searchResults.length); 1047 matchRange = this._regexMatchRanges[this._currentMatchRangeIndex];
1004 this._clearCurrentSearchResultHighlight(); 1048 matchRange.highlightNode.classList.remove(currentSearchResultClassNa me);
1005 this._currentSearchResultIndex = index; 1049 }
1006 this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIn dex); 1050
1007 var currentViewMessageIndex = this._searchResults[index]; 1051 index = mod(index, this._regexMatchRanges.length);
1008 this._viewport.scrollItemIntoView(currentViewMessageIndex); 1052 this._currentMatchRangeIndex = index;
1009 this._visibleViewMessages[currentViewMessageIndex].highlightSearchResult s(this._searchRegex); 1053 this._searchableView.updateCurrentMatchIndex(index);
1054 matchRange = this._regexMatchRanges[index];
1055 matchRange.highlightNode.classList.add(currentSearchResultClassName);
1056 this._viewport.scrollItemIntoView(matchRange.messageIndex);
1057 matchRange.highlightNode.scrollIntoViewIfNeeded();
1010 }, 1058 },
1011 1059
1012 __proto__: WebInspector.VBox.prototype 1060 __proto__: WebInspector.VBox.prototype
1013 } 1061 }
1014 1062
1015 /** 1063 /**
1016 * @constructor 1064 * @constructor
1017 * @extends {WebInspector.Object} 1065 * @extends {WebInspector.Object}
1018 * @param {!WebInspector.ConsoleView} view 1066 * @param {!WebInspector.ConsoleView} view
1019 */ 1067 */
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 * @param {!WebInspector.ConsoleMessage} message 1201 * @param {!WebInspector.ConsoleMessage} message
1154 * @param {!WebInspector.Linkifier} linkifier 1202 * @param {!WebInspector.Linkifier} linkifier
1155 * @param {number} nestingLevel 1203 * @param {number} nestingLevel
1156 */ 1204 */
1157 WebInspector.ConsoleCommand = function(message, linkifier, nestingLevel) 1205 WebInspector.ConsoleCommand = function(message, linkifier, nestingLevel)
1158 { 1206 {
1159 WebInspector.ConsoleViewMessage.call(this, message, linkifier, nestingLevel) ; 1207 WebInspector.ConsoleViewMessage.call(this, message, linkifier, nestingLevel) ;
1160 } 1208 }
1161 1209
1162 WebInspector.ConsoleCommand.prototype = { 1210 WebInspector.ConsoleCommand.prototype = {
1163 clearHighlight: function() 1211 clearHighlights: function()
1164 { 1212 {
1165 var highlightedMessage = this._formattedCommand; 1213 var highlightedMessage = this._formattedCommand;
1166 delete this._formattedCommand; 1214 delete this._formattedCommand;
1167 this._formatCommand(); 1215 this._formatCommand();
1168 this._element.replaceChild(this._formattedCommand, highlightedMessage); 1216 this._element.replaceChild(this._formattedCommand, highlightedMessage);
1169 }, 1217 },
1170 1218
1171 /** 1219 /**
1172 * @param {!RegExp} regexObject
1173 */
1174 highlightSearchResults: function(regexObject)
1175 {
1176 regexObject.lastIndex = 0;
1177 var match = regexObject.exec(this.text);
1178 var matchRanges = [];
1179 while (match) {
1180 matchRanges.push(new WebInspector.SourceRange(match.index, match[0]. length));
1181 match = regexObject.exec(this.text);
1182 }
1183 WebInspector.highlightSearchResults(this._formattedCommand, matchRanges) ;
1184 this._element.scrollIntoViewIfNeeded();
1185 },
1186
1187 /**
1188 * @override 1220 * @override
1189 * @param {!RegExp} regexObject 1221 * @param {!RegExp} regexObject
1190 * @return {boolean} 1222 * @return {boolean}
1191 */ 1223 */
1192 matchesRegex: function(regexObject) 1224 matchesRegex: function(regexObject)
1193 { 1225 {
1194 regexObject.lastIndex = 0; 1226 regexObject.lastIndex = 0;
1195 return regexObject.test(this.text); 1227 return regexObject.test(this.text);
1196 }, 1228 },
1197 1229
(...skipping 12 matching lines...) Expand all
1210 } 1242 }
1211 return this._element; 1243 return this._element;
1212 }, 1244 },
1213 1245
1214 _formatCommand: function() 1246 _formatCommand: function()
1215 { 1247 {
1216 this._formattedCommand = createElementWithClass("span", "console-message -text source-code"); 1248 this._formattedCommand = createElementWithClass("span", "console-message -text source-code");
1217 this._formattedCommand.textContent = this.text; 1249 this._formattedCommand.textContent = this.text;
1218 }, 1250 },
1219 1251
1252 /**
1253 * @override
1254 * @return {string}
1255 */
1256 renderedText: function()
1257 {
1258 return this.text;
1259 },
1260
1261 /**
1262 * @override
1263 * @param {!Array.<!Object>} ranges
1264 * @return {!Array.<!Element>}
1265 */
1266 highlightMatches: function(ranges)
1267 {
1268 var highlightNodes = [];
1269 if (this._formattedCommand) {
1270 highlightNodes = WebInspector.highlightRangesWithStyleClass(this._fo rmattedCommand, ranges, WebInspector.highlightedSearchResultClassName);
1271 }
1272 return highlightNodes;
1273 },
1274
1220 __proto__: WebInspector.ConsoleViewMessage.prototype 1275 __proto__: WebInspector.ConsoleViewMessage.prototype
1221 } 1276 }
1222 1277
1223 /** 1278 /**
1224 * @constructor 1279 * @constructor
1225 * @extends {WebInspector.ConsoleViewMessage} 1280 * @extends {WebInspector.ConsoleViewMessage}
1226 * @param {!WebInspector.ConsoleMessage} message 1281 * @param {!WebInspector.ConsoleMessage} message
1227 * @param {!WebInspector.Linkifier} linkifier 1282 * @param {!WebInspector.Linkifier} linkifier
1228 * @param {number} nestingLevel 1283 * @param {number} nestingLevel
1229 */ 1284 */
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 /** 1371 /**
1317 * @override 1372 * @override
1318 * @return {boolean} 1373 * @return {boolean}
1319 */ 1374 */
1320 handleAction: function() 1375 handleAction: function()
1321 { 1376 {
1322 WebInspector.console.show(); 1377 WebInspector.console.show();
1323 return true; 1378 return true;
1324 } 1379 }
1325 } 1380 }
1381
1382 /**
1383 * @typedef {{messageIndex: number, highlightNode: !Element}}
1384 */
1385 WebInspector.ConsoleView.RegexMatchRange;
OLDNEW
« no previous file with comments | « LayoutTests/inspector/console/console-search-expected.txt ('k') | Source/devtools/front_end/console/ConsoleViewMessage.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698