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

Unified Diff: chrome/browser/resources/settings/search_settings.js

Issue 1952493002: MD Settings: Proof of concept, highlighting search matches across Shadow DOM boundaries. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/resources/settings/settings_resources.grd » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/settings/search_settings.js
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..3a25d0e814524420329eaf28b3196d11bb3f5357
--- /dev/null
+++ b/chrome/browser/resources/settings/search_settings.js
@@ -0,0 +1,139 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+ var WRAPPER_CSS_CLASS = 'search-highlight-wrapper';
+ var HIT_CSS_CLASS = 'search-highlight-hit';
+
+ function findChildren_(element) {
+ var children = [];
+ var walker = document.createTreeWalker(
+ element.shadowRoot, NodeFilter.SHOW_ELEMENTS, null, false);
+ var node = walker.nextNode();
+ while (node) {
+ if (!!node.shadowRoot)
+ children.push(node);
+
+ node = walker.nextNode();
+ }
+ return children;
+ }
+
+ /**
+ * Highlights all matches in the given element. Ignores children that have
+ * their own Shadow DOW.
+ * @param {!RegExp} regexp
+ * @param {!Element} element
+ * @return {boolean} Whether any matches were found.
+ */
+ function highlightSelfMatches_(regExp, element) {
+ var found = false;
+ var walker = document.createTreeWalker(
+ element.shadowRoot, NodeFilter.SHOW_TEXT, null, false);
+
+ var node = walker.nextNode();
+ while (node) {
+ var textContent = node.nodeValue;
+ var tokens = textContent.split(regExp);
+
+ if (node.parentNode.tagName == 'STYLE' || tokens.length == 1) {
+ node = walker.nextNode();
+ continue;
+ }
+
+ var nextNode = walker.nextNode();
+ var parentNode = node.parentNode;
+ // Use existing node as placeholder to determine where to insert the
+ // replacement content.
+
+ var wrapper = document.createElement('span');
+ wrapper.classList.add(WRAPPER_CSS_CLASS);
+ parentNode.insertBefore(wrapper, node);
+
+ for (var i = 0; i < tokens.length; ++i) {
+ if (i % 2 == 0) {
+ wrapper.appendChild(document.createTextNode(tokens[i]));
+ } else {
+ fount = true;
+ var span = document.createElement('span');
+ span.classList.add(HIT_CSS_CLASS);
+ span.style['background-color'] = 'yellow';
+ span.textContent = tokens[i];
+ wrapper.appendChild(span);
+ }
+ }
+
+ // Remove old node.
+ node.remove();
+ node = nextNode;
+ }
+
+ return found;
+ }
+
+ /**
+ * Un-highlights all previous matches in the given element. It ignores
+ * children that have their own Shadow DOM.
+ * @param {!Element} element
+ */
+ function unhighlightSelfMatches_(element) {
+ var wrappers = element.shadowRoot.querySelectorAll('.' + WRAPPER_CSS_CLASS);
+ wrappers.forEach(function(wrapper) {
+ wrapperParent = wrapper.parentElement;
+ var elements = wrapper.querySelectorAll('.' + HIT_CSS_CLASS);
+ // For each element, remove the highlighting.
+ for (var i = 0; i < elements.length; i++) {
+ var node = elements[i];
+ wrapper.replaceChild(node.firstChild, node);
+ }
+
+ // Normalize so that adjacent text nodes will be combined.
+ wrapper.normalize();
+ // Restore the DOM structure as it was before the search occurred.
+ wrapperParent.appendChild(wrapper.firstChild);
+ wrapper.remove();
+ });
+ }
+
+ /**
+ * Highlights all matches (both within self and children's Shadow DOM).
+ * @param {!RegExp} regexp
+ * @param {!Element} element
+ */
+ function highlightMatches_(regexp, element) {
+ highlightSelfMatches_(regexp, element);
+ findChildren_(element).forEach(function(child) {
+ highlightMatches_(regexp, child);
+ });
+ }
+
+ /**
+ * Un-highlights all previous matches (both within self and children's Shadow
+ * DOM).
+ * @param {!Element} element
+ */
+ function unhighlightMatches_(element) {
+ unhighlightSelfMatches_(element);
+ findChildren_(element).forEach(unhighlightMatches_);
+ }
+
+ /**
+ * Performs hierarchical search, starting at the given element.
+ * @param {string} text
+ * @param {!Element} element
+ */
+ function search(text, element) {
+ unhighlightMatches_(element);
+
+ var searchText =
+ text.trim().toLowerCase().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+ if (searchText.length == 0) {
+ return;
+ }
+
+ highlightMatches_(new RegExp('(' + searchText + ')', 'ig'), element);
+ }
+
+ window.search = search;
+})();
« no previous file with comments | « no previous file | chrome/browser/resources/settings/settings_resources.grd » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698