Fix copy & paste issue on diff list page As multiple gr-diff on the list page, when process the selection, should process the one with a valid selection. Change-Id: Id8a3e05b7c898b7572b433f34c7bc1a38136f713
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;