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

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: Consolidate test suites Created 6 years 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 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 this._currentGroup = this._currentGroup.parentGroup(); 581 this._currentGroup = this._currentGroup.parentGroup();
577 return; 582 return;
578 } 583 }
579 if (!this._currentGroup.messagesHidden()) { 584 if (!this._currentGroup.messagesHidden()) {
580 var originatingMessage = viewMessage.consoleMessage().originatingMes sage(); 585 var originatingMessage = viewMessage.consoleMessage().originatingMes sage();
581 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage) 586 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage)
582 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result"); 587 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result");
583 588
584 this._visibleViewMessages.push(viewMessage); 589 this._visibleViewMessages.push(viewMessage);
585 590
586 if (this._searchRegex && viewMessage.matchesRegex(this._searchRegex) ) { 591 if (this._searchRegex && this._searchMessage(this._visibleViewMessag es.length - 1))
587 this._searchResults.push(viewMessage); 592 this._searchableView.updateSearchMatchesCount(this._regexMatchRa nges.length);
588 this._searchableView.updateSearchMatchesCount(this._searchResult s.length);
589 }
590 } 593 }
591 594
592 if (viewMessage.consoleMessage().isGroupStartMessage()) 595 if (viewMessage.consoleMessage().isGroupStartMessage())
593 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage); 596 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage);
594 }, 597 },
595 598
596 /** 599 /**
597 * @param {!WebInspector.ConsoleMessage} message 600 * @param {!WebInspector.ConsoleMessage} message
598 * @return {!WebInspector.ConsoleViewMessage} 601 * @return {!WebInspector.ConsoleViewMessage}
599 */ 602 */
600 _createViewMessage: function(message) 603 _createViewMessage: function(message)
601 { 604 {
602 var nestingLevel = this._currentGroup.nestingLevel(); 605 var nestingLevel = this._currentGroup.nestingLevel();
603 switch (message.type) { 606 switch (message.type) {
604 case WebInspector.ConsoleMessage.MessageType.Command: 607 case WebInspector.ConsoleMessage.MessageType.Command:
605 return new WebInspector.ConsoleCommand(message, this._linkifier, nes tingLevel); 608 return new WebInspector.ConsoleCommand(message, this._linkifier, nes tingLevel);
606 case WebInspector.ConsoleMessage.MessageType.Result: 609 case WebInspector.ConsoleMessage.MessageType.Result:
607 return new WebInspector.ConsoleCommandResult(message, this._linkifie r, nestingLevel); 610 return new WebInspector.ConsoleCommandResult(message, this._linkifie r, nestingLevel);
608 case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed: 611 case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed:
609 case WebInspector.ConsoleMessage.MessageType.StartGroup: 612 case WebInspector.ConsoleMessage.MessageType.StartGroup:
610 return new WebInspector.ConsoleGroupViewMessage(message, this._linki fier, nestingLevel); 613 return new WebInspector.ConsoleGroupViewMessage(message, this._linki fier, nestingLevel);
611 default: 614 default:
612 return new WebInspector.ConsoleViewMessage(message, this._linkifier, nestingLevel); 615 return new WebInspector.ConsoleViewMessage(message, this._linkifier, nestingLevel);
613 } 616 }
614 }, 617 },
615 618
616 _consoleCleared: function() 619 _consoleCleared: function()
617 { 620 {
618 this._clearCurrentSearchResultHighlight(); 621 this._clearSearchResultHighlights();
619 this._consoleMessages = []; 622 this._consoleMessages = [];
620 this._updateMessageList(); 623 this._updateMessageList();
621 624
622 if (this._searchRegex) 625 if (this._searchRegex)
623 this._searchableView.updateSearchMatchesCount(0); 626 this._searchableView.updateSearchMatchesCount(0);
624 627
625 this._linkifier.reset(); 628 this._linkifier.reset();
626 }, 629 },
627 630
628 _handleContextMenuEvent: function(event) 631 _handleContextMenuEvent: function(event)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 return true; 689 return true;
687 } 690 }
688 691
689 return false; 692 return false;
690 }, 693 },
691 694
692 _updateMessageList: function() 695 _updateMessageList: function()
693 { 696 {
694 this._topGroup = WebInspector.ConsoleGroup.createTopGroup(); 697 this._topGroup = WebInspector.ConsoleGroup.createTopGroup();
695 this._currentGroup = this._topGroup; 698 this._currentGroup = this._topGroup;
696 this._searchResults = []; 699 this._regexMatchRanges = [];
697 this._hiddenByFilterCount = 0; 700 this._hiddenByFilterCount = 0;
698 for (var i = 0; i < this._visibleViewMessages.length; ++i) { 701 for (var i = 0; i < this._visibleViewMessages.length; ++i) {
699 this._visibleViewMessages[i].resetCloseGroupDecorationCount(); 702 this._visibleViewMessages[i].resetCloseGroupDecorationCount();
700 this._visibleViewMessages[i].resetIncrementRepeatCount(); 703 this._visibleViewMessages[i].resetIncrementRepeatCount();
701 } 704 }
702 this._visibleViewMessages = []; 705 this._visibleViewMessages = [];
703 for (var i = 0; i < this._consoleMessages.length; ++i) 706 for (var i = 0; i < this._consoleMessages.length; ++i)
704 this._appendMessageToEnd(this._consoleMessages[i]); 707 this._appendMessageToEnd(this._consoleMessages[i]);
705 this._updateFilterStatus(); 708 this._updateFilterStatus();
706 this._viewport.invalidate(); 709 this._viewport.invalidate();
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 elementsToRestoreScrollPositionsFor: function() 907 elementsToRestoreScrollPositionsFor: function()
905 { 908 {
906 return [this._messagesElement]; 909 return [this._messagesElement];
907 }, 910 },
908 911
909 /** 912 /**
910 * @override 913 * @override
911 */ 914 */
912 searchCanceled: function() 915 searchCanceled: function()
913 { 916 {
914 this._clearCurrentSearchResultHighlight(); 917 this._clearSearchResultHighlights();
915 delete this._searchResults; 918 this._regexMatchRanges = [];
916 delete this._searchRegex; 919 delete this._searchRegex;
917 this._viewport.refresh(); 920 this._viewport.refresh();
918 }, 921 },
919 922
920 /** 923 /**
921 * @override 924 * @override
922 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig 925 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
923 * @param {boolean} shouldJump 926 * @param {boolean} shouldJump
924 * @param {boolean=} jumpBackwards 927 * @param {boolean=} jumpBackwards
925 */ 928 */
926 performSearch: function(searchConfig, shouldJump, jumpBackwards) 929 performSearch: function(searchConfig, shouldJump, jumpBackwards)
927 { 930 {
928 var query = searchConfig.query; 931 var query = searchConfig.query;
929 this.searchCanceled(); 932 this.searchCanceled();
930 this._searchableView.updateSearchMatchesCount(0); 933 this._searchableView.updateSearchMatchesCount(0);
931 this._searchRegex = createPlainTextSearchRegex(query, "gi"); 934 this._searchRegex = createPlainTextSearchRegex(query, "gi");
932 935
933 /** @type {!Array.<number>} */ 936 this._regexMatchRanges = [];
934 this._searchResults = []; 937 this._currentMatchRangeIndex = -1;
935 for (var i = 0; i < this._visibleViewMessages.length; i++) { 938 for (var i = 0; i < this._visibleViewMessages.length; i++)
936 if (this._visibleViewMessages[i].matchesRegex(this._searchRegex)) 939 this._searchMessage(i);
937 this._searchResults.push(i); 940 this._searchableView.updateSearchMatchesCount(this._regexMatchRanges.len gth);
941 if (shouldJump)
942 this._jumpToMatch(jumpBackwards ? -1 : 0);
943 this._viewport.refresh();
944 },
945
946 /**
947 * @param {number} index
lushnikov 2014/12/04 16:07:34 @return annotation is missing
aknudsen 2014/12/05 22:30:02 Done.
948 */
949 _searchMessage: function(index)
950 {
951 // Reset regex wrt. global search.
952 this._searchRegex.lastIndex = 0;
953
954 var message = this._visibleViewMessages[index];
955 var text = message.getText();
956 var match;
957 var matchRanges = [];
958 var sourceRanges = [];
959 while ((match = this._searchRegex.exec(text)) && match[0]) {
960 matchRanges.push({
961 messageIndex: index,
962 highlightNode: null,
963 });
964 sourceRanges.push(new WebInspector.SourceRange(match.index, match[0] .length));
938 } 965 }
939 this._searchableView.updateSearchMatchesCount(this._searchResults.length ); 966
940 this._currentSearchResultIndex = -1; 967 var matchRange;
941 if (shouldJump && this._searchResults.length) 968 var highlightNodes = message.highlightMatches(sourceRanges);
942 this._jumpToSearchResult(jumpBackwards ? -1 : 0); 969 for (var i = 0; i < matchRanges.length; ++i) {
943 this._viewport.refresh(); 970 matchRange = matchRanges[i];
971 matchRange.highlightNode = highlightNodes[i];
972 this._regexMatchRanges.push(matchRange);
973 }
974
975 return !!matchRange;
944 }, 976 },
945 977
946 /** 978 /**
947 * @override 979 * @override
948 */ 980 */
949 jumpToNextSearchResult: function() 981 jumpToNextSearchResult: function()
950 { 982 {
951 if (!this._searchResults || !this._searchResults.length) 983 this._jumpToMatch(this._currentMatchRangeIndex + 1);
952 return;
953 this._jumpToSearchResult(this._currentSearchResultIndex + 1);
954 }, 984 },
955 985
956 /** 986 /**
957 * @override 987 * @override
958 */ 988 */
959 jumpToPreviousSearchResult: function() 989 jumpToPreviousSearchResult: function()
960 { 990 {
961 if (!this._searchResults || !this._searchResults.length) 991 this._jumpToMatch(this._currentMatchRangeIndex - 1);
962 return;
963 this._jumpToSearchResult(this._currentSearchResultIndex - 1);
964 }, 992 },
965 993
966 /** 994 /**
967 * @override 995 * @override
968 * @return {boolean} 996 * @return {boolean}
969 */ 997 */
970 supportsCaseSensitiveSearch: function() 998 supportsCaseSensitiveSearch: function()
971 { 999 {
972 return false; 1000 return false;
973 }, 1001 },
974 1002
975 /** 1003 /**
976 * @override 1004 * @override
977 * @return {boolean} 1005 * @return {boolean}
978 */ 1006 */
979 supportsRegexSearch: function() 1007 supportsRegexSearch: function()
980 { 1008 {
981 return false; 1009 return false;
982 }, 1010 },
983 1011
984 _clearCurrentSearchResultHighlight: function() 1012 _clearSearchResultHighlights: function()
985 { 1013 {
986 if (!this._searchResults) 1014 for (var i = 0; i < this._regexMatchRanges.length; ++i) {
1015 var matchRange = this._regexMatchRanges[i];
1016 var message = this._visibleViewMessages[matchRange.messageIndex];
1017 if (message)
1018 message.clearHighlights();
1019 }
1020 this._currentMatchRangeIndex = -1;
1021 },
1022
1023 /**
1024 * @param {number} index
1025 */
1026 _jumpToMatch: function(index)
1027 {
1028 if (!this._regexMatchRanges.length)
987 return; 1029 return;
988 1030
989 var highlightedViewMessage = this._visibleViewMessages[this._searchResul ts[this._currentSearchResultIndex]]; 1031 var currentSearchResultClassName = "current-search-result";
990 if (highlightedViewMessage)
991 highlightedViewMessage.clearHighlight();
992 this._currentSearchResultIndex = -1;
993 },
994 1032
995 _jumpToSearchResult: function(index) 1033 var matchRange;
996 { 1034 if (this._currentMatchRangeIndex >= 0) {
997 index = mod(index, this._searchResults.length); 1035 matchRange = this._regexMatchRanges[this._currentMatchRangeIndex];
998 this._clearCurrentSearchResultHighlight(); 1036 matchRange.highlightNode.classList.remove(currentSearchResultClassNa me);
999 this._currentSearchResultIndex = index; 1037 }
1000 this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIn dex); 1038
1001 var currentViewMessageIndex = this._searchResults[index]; 1039 index = mod(index, this._regexMatchRanges.length);
1002 this._viewport.scrollItemIntoView(currentViewMessageIndex); 1040 this._currentMatchRangeIndex = index;
1003 this._visibleViewMessages[currentViewMessageIndex].highlightSearchResult s(this._searchRegex); 1041 this._searchableView.updateCurrentMatchIndex(index);
1042 matchRange = this._regexMatchRanges[index];
1043 matchRange.highlightNode.classList.add(currentSearchResultClassName);
1044 // Scroll the message itself into view
1045 this._viewport.scrollItemIntoView(matchRange.messageIndex);
1046 // In case the highlight node is in a tree element, it must be scrolled into view,
1047 // the message itself must first be scrolled into view though.
1048 matchRange.highlightNode.scrollIntoViewIfNeeded();
1004 }, 1049 },
1005 1050
1006 __proto__: WebInspector.VBox.prototype 1051 __proto__: WebInspector.VBox.prototype
1007 } 1052 }
1008 1053
1009 /** 1054 /**
1010 * @constructor 1055 * @constructor
1011 * @extends {WebInspector.Object} 1056 * @extends {WebInspector.Object}
1012 * @param {!WebInspector.ConsoleView} view 1057 * @param {!WebInspector.ConsoleView} view
1013 */ 1058 */
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 * @param {!WebInspector.ConsoleMessage} message 1192 * @param {!WebInspector.ConsoleMessage} message
1148 * @param {!WebInspector.Linkifier} linkifier 1193 * @param {!WebInspector.Linkifier} linkifier
1149 * @param {number} nestingLevel 1194 * @param {number} nestingLevel
1150 */ 1195 */
1151 WebInspector.ConsoleCommand = function(message, linkifier, nestingLevel) 1196 WebInspector.ConsoleCommand = function(message, linkifier, nestingLevel)
1152 { 1197 {
1153 WebInspector.ConsoleViewMessage.call(this, message, linkifier, nestingLevel) ; 1198 WebInspector.ConsoleViewMessage.call(this, message, linkifier, nestingLevel) ;
1154 } 1199 }
1155 1200
1156 WebInspector.ConsoleCommand.prototype = { 1201 WebInspector.ConsoleCommand.prototype = {
1157 clearHighlight: function() 1202 clearHighlights: function()
1158 { 1203 {
1159 var highlightedMessage = this._formattedCommand; 1204 var highlightedMessage = this._formattedCommand;
1160 delete this._formattedCommand; 1205 delete this._formattedCommand;
1161 this._formatCommand(); 1206 this._formatCommand();
1162 this._element.replaceChild(this._formattedCommand, highlightedMessage); 1207 this._element.replaceChild(this._formattedCommand, highlightedMessage);
1163 }, 1208 },
1164 1209
1165 /** 1210 /**
1166 * @param {!RegExp} regexObject
1167 */
1168 highlightSearchResults: function(regexObject)
1169 {
1170 regexObject.lastIndex = 0;
1171 var match = regexObject.exec(this.text);
1172 var matchRanges = [];
1173 while (match) {
1174 matchRanges.push(new WebInspector.SourceRange(match.index, match[0]. length));
1175 match = regexObject.exec(this.text);
1176 }
1177 WebInspector.highlightSearchResults(this._formattedCommand, matchRanges) ;
1178 this._element.scrollIntoViewIfNeeded();
1179 },
1180
1181 /**
1182 * @override 1211 * @override
1183 * @param {!RegExp} regexObject 1212 * @param {!RegExp} regexObject
1184 * @return {boolean} 1213 * @return {boolean}
1185 */ 1214 */
1186 matchesRegex: function(regexObject) 1215 matchesRegex: function(regexObject)
1187 { 1216 {
1188 regexObject.lastIndex = 0; 1217 regexObject.lastIndex = 0;
1189 return regexObject.test(this.text); 1218 return regexObject.test(this.text);
1190 }, 1219 },
1191 1220
(...skipping 12 matching lines...) Expand all
1204 } 1233 }
1205 return this._element; 1234 return this._element;
1206 }, 1235 },
1207 1236
1208 _formatCommand: function() 1237 _formatCommand: function()
1209 { 1238 {
1210 this._formattedCommand = createElementWithClass("span", "console-message -text source-code"); 1239 this._formattedCommand = createElementWithClass("span", "console-message -text source-code");
1211 this._formattedCommand.textContent = this.text; 1240 this._formattedCommand.textContent = this.text;
1212 }, 1241 },
1213 1242
1243 /**
1244 * @override
1245 * @return {string}
1246 */
1247 getText: function()
1248 {
1249 return this.text;
1250 },
1251
1252 /**
1253 * @override
1254 * @param {!Array.<!Object>} ranges
1255 * @return {!Array.<!Element>}
1256 */
1257 highlightMatches: function(ranges)
1258 {
1259 var highlightNodes = [];
1260 if (this._formattedCommand) {
1261 highlightNodes = WebInspector.highlightRangesWithStyleClass(this._fo rmattedCommand, ranges, WebInspector.highlightedSearchResultClassName);
1262 }
1263 return highlightNodes;
1264 },
1265
1214 __proto__: WebInspector.ConsoleViewMessage.prototype 1266 __proto__: WebInspector.ConsoleViewMessage.prototype
1215 } 1267 }
1216 1268
1217 /** 1269 /**
1218 * @constructor 1270 * @constructor
1219 * @extends {WebInspector.ConsoleViewMessage} 1271 * @extends {WebInspector.ConsoleViewMessage}
1220 * @param {!WebInspector.ConsoleMessage} message 1272 * @param {!WebInspector.ConsoleMessage} message
1221 * @param {!WebInspector.Linkifier} linkifier 1273 * @param {!WebInspector.Linkifier} linkifier
1222 * @param {number} nestingLevel 1274 * @param {number} nestingLevel
1223 */ 1275 */
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 /** 1362 /**
1311 * @override 1363 * @override
1312 * @return {boolean} 1364 * @return {boolean}
1313 */ 1365 */
1314 handleAction: function() 1366 handleAction: function()
1315 { 1367 {
1316 WebInspector.console.show(); 1368 WebInspector.console.show();
1317 return true; 1369 return true;
1318 } 1370 }
1319 } 1371 }
1372
1373 /**
1374 * @typedef {{messageIndex: number, highlightNode: !Element}}
1375 */
1376 WebInspector.ConsoleView.RegexMatchRange;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698