Index: third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js |
index 7755b1cdc7fc565c0af853c00ba39addfbd23400..f15c29c9fc68e5d0257db86096ce10edddf5995a 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js |
+++ b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js |
@@ -42,10 +42,14 @@ function TreeOutline(nonFocusable) |
this._contentElement = this._rootElement._childrenListNode; |
this._contentElement.addEventListener("keydown", this._treeKeyDown.bind(this), true); |
+ this._contentElement.addEventListener("keypress", this._treeKeyPress.bind(this), true); |
this.setFocusable(!nonFocusable); |
this.element = this._contentElement; |
+ |
+ this.element.addEventListener("blur", this._handleBlur.bind(this), true); |
+ this.element.addEventListener("click", this._handleClick.bind(this), true); |
} |
TreeOutline.Events = { |
@@ -64,6 +68,11 @@ TreeOutline.prototype = { |
this._rootElement.selectable = false; |
this._rootElement.expanded = true; |
this._rootElement._childrenListNode.classList.remove("children"); |
+ |
+ this._currentSelectionFilterString = ''; |
pfeldman
2016/03/14 23:51:35
Please only use double quotes.
Allada-Google
2016/03/15 17:13:08
Done.
|
+ this._currentSelectionFilter = null; |
pfeldman
2016/03/14 23:51:34
You should declare a type here using JSDoc.
Allada-Google
2016/03/15 17:13:07
Done.
|
+ this._highlightChanges = []; |
+ this._interactiveFilterEnabled = false; |
}, |
/** |
@@ -75,6 +84,79 @@ TreeOutline.prototype = { |
}, |
/** |
+ * This will also set/override the RegExp to filter on (ie: setCurrentSelectionFilter()) |
pfeldman
2016/03/14 23:51:34
We don't explain why (in Blink)...
Allada-Google
2016/03/15 17:13:08
Done.
|
+ * @param {string} filterString String to filter text on. |
pfeldman
2016/03/14 23:51:35
or what... Just the types.
Allada-Google
2016/03/15 17:13:08
Done.
|
+ */ |
+ setCurrentSelectionFilterString: function (filterString) |
pfeldman
2016/03/14 23:51:35
Seems to be private (starts with _)
Allada-Google
2016/03/15 17:13:08
Done.
|
+ { |
+ this._currentSelectionFilterString = filterString; |
+ if (this._currentSelectionFilterString === '') |
pfeldman
2016/03/14 23:51:34
""
Allada-Google
2016/03/15 17:13:08
Done.
|
+ this.setCurrentSelectionFilter(null); |
+ else |
+ this.setCurrentSelectionFilter(new RegExp(['(', this._currentSelectionFilterString.escapeForRegExp(), ')'].join(''), 'i')); |
+ }, |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ currentSelectionFilterString: function () |
pfeldman
2016/03/14 23:51:34
lets not expose until required.
Allada-Google
2016/03/15 17:13:08
Done.
|
+ { |
+ |
+ return this._currentSelectionFilterString; |
+ }, |
+ |
+ setInteractiveFilterable: function (enable) |
pfeldman
2016/03/14 23:51:34
JSDoc for enable type.
Allada-Google
2016/03/15 17:13:07
Done.
|
+ { |
+ this._interactiveFilterEnabled = !!enable; |
pfeldman
2016/03/14 23:51:34
Declare it as a boolean and there would be no need
Allada-Google
2016/03/15 17:13:08
Done.
|
+ }, |
+ |
+ /** |
+ * @param {?RegExp} filterRegExp Regular Expression to use to filter selectable items |
+ */ |
+ setCurrentSelectionFilter: function (filterRegExp) |
+ { |
+ var currentFilter = this._currentSelectionFilter; |
+ this._currentSelectionFilter = filterRegExp; |
+ |
+ if (this._highlightChanges && this._highlightChanges.length > 0) |
pfeldman
2016/03/14 23:51:34
(this._highlightChanges && this._highlightChanges.
Allada-Google
2016/03/15 17:13:08
Done.
|
+ WebInspector.revertDomChanges(this._highlightChanges); |
pfeldman
2016/03/14 23:51:34
We are now vulnerable to the changes made to the e
Allada-Google
2016/03/15 17:13:08
Done.
|
+ this._highlightChanges = []; |
+ |
+ if (filterRegExp && filterRegExp !== currentFilter) { |
pfeldman
2016/03/14 23:51:34
We prefer early returns to nested conditions.
Allada-Google
2016/03/15 17:13:08
Done.
|
+ // If the list is not fully rendered don't try and continue |
+ if (this._rootElement) { |
pfeldman
2016/03/14 23:51:34
ditto
Allada-Google
2016/03/15 17:13:08
Done.
|
+ var textNode = this._rootElement.firstChild(); |
pfeldman
2016/03/14 23:51:35
textNode is not really a text node, it is a first
|
+ var childTextNodes = this.element.childTextNodes(); |
pfeldman
2016/03/14 23:51:34
unused?
|
+ var newExp = new RegExp(filterRegExp.source, 'gi'); |
pfeldman
2016/03/14 23:51:34
"gi", also, why new regex?
Allada-Google
2016/03/15 17:13:08
Done.
|
+ |
+ if (this.selectedTreeElement && !this.selectedTreeElement.selectable) |
+ this.selectNext() || this.selectPrevious(); |
+ |
+ do { |
+ var match; |
+ var ranges = []; |
+ var textContent = textNode._listItemNode.textContent; |
+ while ((match = newExp.exec(textContent)) !== null) { |
pfeldman
2016/03/14 23:51:35
drop !== null, extract match from comparison into
Allada-Google
2016/03/15 17:13:08
Done.
|
+ ranges.push(new WebInspector.SourceRange(match.index, match[0].length)); |
+ } |
+ if (ranges.length > 0) |
+ WebInspector.highlightRangesWithStyleClass(textNode._listItemNode, ranges, "tree-text-interactive-highlight", this._highlightChanges); |
+ |
+ textNode = textNode.traverseNextTreeElement(true, null, true); |
+ } while(textNode); |
+ } |
+ } |
+ }, |
+ |
+ /** |
+ * @return {?RegExp} |
+ */ |
+ currentSelectionFilter: function () |
pfeldman
2016/03/14 23:51:34
do not expose
Allada-Google
2016/03/15 17:13:08
Done.
|
+ { |
+ return this._currentSelectionFilter; |
+ }, |
+ |
+ /** |
* @return {?TreeElement} |
*/ |
firstChild: function() |
@@ -187,6 +269,15 @@ TreeOutline.prototype = { |
}, |
/** |
+ * @param {!TreeElement} treeElement |
+ * @return {boolean} |
+ */ |
+ checkFilter: function (treeElement) |
pfeldman
2016/03/14 23:51:34
ditto
Allada-Google
2016/03/15 17:13:08
Done.
|
+ { |
+ return this.currentSelectionFilter() ? this.currentSelectionFilter().test(treeElement.titleText) : true; |
+ }, |
+ |
+ /** |
* @return {boolean} |
*/ |
selectPrevious: function() |
@@ -221,6 +312,24 @@ TreeOutline.prototype = { |
/** |
* @param {!Event} event |
*/ |
+ _handleClick: function (event) |
+ { |
+ if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(''); |
pfeldman
2016/03/14 23:51:34
""
Allada-Google
2016/03/15 17:13:08
Done.
|
+ }, |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _handleBlur: function (event) |
+ { |
+ if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(''); |
+ }, |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
_treeKeyDown: function(event) |
{ |
if (event.target !== this._contentElement) |
@@ -229,30 +338,33 @@ TreeOutline.prototype = { |
if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey) |
return; |
+ var currentFilterString = this.currentSelectionFilterString(); |
var handled = false; |
+ var key = event.keyCode; |
var nextSelectedElement; |
- if (event.keyIdentifier === "Up" && !event.altKey) { |
- handled = this.selectPrevious(); |
- } else if (event.keyIdentifier === "Down" && !event.altKey) { |
- handled = this.selectNext(); |
- } 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(); |
+ |
+ switch (key) { |
+ case WebInspector.KeyboardShortcut.Keys.Esc.code: |
+ if (this._interactiveFilterEnabled) { |
+ if (currentFilterString.length !== 0) |
pfeldman
2016/03/14 23:51:35
drop !== 0
Allada-Google
2016/03/15 17:13:08
Done.
|
+ // Consider the item handled if the filter string is already set (this will keep the console from triggering) |
+ handled = true; |
+ this.setCurrentSelectionFilterString(''); |
} |
- } else if (event.keyIdentifier === "Right") { |
+ break; |
+ case WebInspector.KeyboardShortcut.Keys.Delete.code: |
+ if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(''); |
+ case WebInspector.KeyboardShortcut.Keys.Backspace.code: |
+ if (this._interactiveFilterEnabled === false || currentFilterString.length === 0) |
+ handled = this.selectedTreeElement.ondelete(); |
+ else if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(currentFilterString.substr(0, currentFilterString.length - 1)); |
+ break; |
+ case WebInspector.KeyboardShortcut.Keys.Right.code: |
pfeldman
2016/03/14 23:51:34
Group these and use case fallthrough to handle the
Allada-Google
2016/03/15 17:13:08
I optimized the code I added here as much as I fou
|
+ if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(''); |
+ |
if (!this.selectedTreeElement.revealed()) { |
this.selectedTreeElement.reveal(); |
handled = true; |
@@ -270,12 +382,49 @@ TreeOutline.prototype = { |
this.selectedTreeElement.expand(); |
} |
} |
- } else if (event.keyCode === 8 /* Backspace */ || event.keyCode === 46 /* Delete */) |
- 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(); |
+ break; |
+ case WebInspector.KeyboardShortcut.Keys.Left.code: |
+ if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(''); |
+ |
+ 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(); |
+ } |
+ break; |
+ case WebInspector.KeyboardShortcut.Keys.Down.code: |
+ if (!event.altKey) |
+ handled = this.selectNext(); |
+ break; |
+ case WebInspector.KeyboardShortcut.Keys.Up.code: |
+ if (!event.altKey) |
+ handled = this.selectPrevious(); |
+ break; |
+ case WebInspector.KeyboardShortcut.Keys.Space.code: |
+ // Do not send space key event if the search filter has stuff in buffer |
+ if (currentFilterString.length === 0) |
+ handled = this.selectedTreeElement.onspace(); |
+ break; |
+ default: |
+ if (isEnterKey(event)) { |
+ if (this._interactiveFilterEnabled) |
+ this.setCurrentSelectionFilterString(''); |
+ |
+ handled = this.selectedTreeElement.onenter(); |
+ } |
+ } |
if (nextSelectedElement) { |
nextSelectedElement.reveal(); |
@@ -287,6 +436,35 @@ TreeOutline.prototype = { |
}, |
/** |
+ * @param {!Event} event |
+ */ |
+ _treeKeyPress: function (event) |
+ { |
+ if (this._interactiveFilterEnabled === false) |
pfeldman
2016/03/14 23:51:34
!this._interactiveFilterEnabled
Allada-Google
2016/03/15 17:13:08
Done.
|
+ return; |
+ |
+ if (event.target !== this._contentElement) |
+ return; |
+ |
+ if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey) |
+ return; |
+ |
+ var currentFilterString = this.currentSelectionFilterString(); |
+ |
+ switch (event.data) { |
+ case "\r": |
+ case "\n": |
+ break; |
+ case " ": |
+ if (currentFilterString.length === 0) { |
+ break; |
+ } |
+ default: |
+ this.setCurrentSelectionFilterString(currentFilterString + event.data); |
+ } |
+ }, |
+ |
+ /** |
* @param {!TreeElement} treeElement |
* @param {boolean} center |
*/ |
@@ -360,6 +538,7 @@ function TreeElement(title, expandable) |
this._listItemNode = createElement("li"); |
this._listItemNode.treeElement = this; |
+ this.titleText = null; |
pfeldman
2016/03/14 23:51:34
Lets compute this dynamically off element's text c
|
if (title) |
this.title = title; |
this._listItemNode.addEventListener("mousedown", this._handleMouseDown.bind(this), false); |
@@ -603,7 +782,7 @@ TreeElement.prototype = { |
get selectable() |
{ |
- if (this._hidden) |
+ if (this._hidden || !this.treeOutline.checkFilter(this)) |
return false; |
return this._selectable; |
}, |
@@ -641,6 +820,7 @@ TreeElement.prototype = { |
this._titleElement = createElementWithClass("span", "tree-element-title"); |
this._titleElement.textContent = x; |
this.tooltip = x; |
+ this.titleText = x; |
} else { |
this._titleElement = x; |
this.tooltip = ""; |