Merge "Fix copy & paste issue on diff list page"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
index 359a039..e46f959 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
@@ -192,15 +192,20 @@
}
}
- /**
- * For Polymer 2, use shadowRoot.getSelection instead.
- */
_getSelection() {
- const diffHost = util.querySelector(document.body, 'gr-diff');
- const selection = diffHost &&
- diffHost.shadowRoot &&
- diffHost.shadowRoot.getSelection();
- return selection ? selection: window.getSelection();
+ const diffHosts = util.querySelectorAll(document.body, 'gr-diff');
+ if (!diffHosts.length) return window.getSelection();
+
+ const curDiffHost = diffHosts.find(diffHost => {
+ if (!diffHost || !diffHost.shadowRoot) return false;
+ const selection = diffHost.shadowRoot.getSelection();
+ // Pick the one with valid selection:
+ // https://developer.mozilla.org/en-US/docs/Web/API/Selection/type
+ return selection && selection.type !== 'None';
+ });
+
+ return curDiffHost ?
+ curDiffHost.shadowRoot.getSelection(): window.getSelection();
}
/**
diff --git a/polygerrit-ui/app/scripts/util.js b/polygerrit-ui/app/scripts/util.js
index 672c43f..565b9b3 100644
--- a/polygerrit-ui/app/scripts/util.js
+++ b/polygerrit-ui/app/scripts/util.js
@@ -105,7 +105,7 @@
*/
util.querySelector = (el, selector) => {
let nodes = [el];
- let element = null;
+ let result = null;
while (nodes.length) {
const node = nodes.pop();
@@ -113,19 +113,49 @@
if (!node || !node.querySelector) continue;
// Try find it with native querySelector directly
- element = node.querySelector(selector);
+ result = node.querySelector(selector);
- if (element) {
+ if (result) {
break;
- } else if (node.shadowRoot) {
- // If shadowHost detected, add the host and its children
- nodes = nodes.concat(Array.from(node.children));
- nodes.push(node.shadowRoot);
- } else {
- nodes = nodes.concat(Array.from(node.children));
}
+
+ // Add all nodes with shadowRoot and loop through
+ const allShadowNodes = [...node.querySelectorAll('*')]
+ .filter(child => !!child.shadowRoot)
+ .map(child => child.shadowRoot);
+ nodes = nodes.concat(allShadowNodes);
}
- return element;
+ return result;
+ };
+
+ /**
+ * Query selector all dom elements matching with certain selector.
+ *
+ * This is shadow DOM compatible, but only works when selector is within
+ * one shadow host, won't work if your selector is crossing
+ * multiple shadow hosts.
+ *
+ * Note: this can be very expensive, only use when have to.
+ */
+ util.querySelectorAll = (el, selector) => {
+ let nodes = [el];
+ const results = new Set();
+ while (nodes.length) {
+ const node = nodes.pop();
+
+ if (!node || !node.querySelectorAll) continue;
+
+ // Try find all from regular children
+ [...node.querySelectorAll(selector)]
+ .forEach(el => results.add(el));
+
+ // Add all nodes with shadowRoot and loop through
+ const allShadowNodes = [...node.querySelectorAll('*')]
+ .filter(child => !!child.shadowRoot)
+ .map(child => child.shadowRoot);
+ nodes = nodes.concat(allShadowNodes);
+ }
+ return [...results];
};
window.util = util;