From 876257f4e219acc06bd5097dd4bd71eb5403ebd2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Sun, 10 Sep 2017 14:23:33 +0100 Subject: [PATCH 1/2] Consolidate the code copy button Adding the code code button was done by manipulating the HTML of the event body to add a span tag, then adding the onclick handler after the thing was mounted. Apart from splitting the code between two places, adding the span tag was, according to Chrome's profiler, taking up quite a lot of CPU cycles (apparently as soon as you set the innerHTML on a div). Instead, just build the whole lot together after the component mounts. --- src/HtmlUtils.js | 18 ------------------ src/components/views/messages/TextualBody.js | 15 +++++++++------ 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index ccc7c1a630..2b0fd686c0 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -393,7 +393,6 @@ export function bodyToHtml(content, highlights, opts) { } safeBody = sanitizeHtml(body, sanitizeHtmlParams); safeBody = unicodeToImage(safeBody); - if (isHtml) safeBody = addCodeCopyButton(safeBody); } finally { delete sanitizeHtmlParams.textFilter; @@ -412,23 +411,6 @@ export function bodyToHtml(content, highlights, opts) { return ; } -function addCodeCopyButton(safeBody) { - // Adds 'copy' buttons to pre blocks - // Note that this only manipulates the markup to add the buttons: - // we need to add the event handlers once the nodes are in the DOM - // since we can't save functions in the markup. - // This is done in TextualBody - const el = document.createElement("div"); - el.innerHTML = safeBody; - const codeBlocks = Array.from(el.getElementsByTagName("pre")); - codeBlocks.forEach(p => { - const button = document.createElement("span"); - button.className = "mx_EventTile_copyButton"; - p.appendChild(button); - }); - return el.innerHTML; -} - export function emojifyText(text) { return { __html: unicodeToImage(escape(text)), diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 58273bee67..3937780c2a 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -113,14 +113,17 @@ module.exports = React.createClass({ } }, 10); } - // add event handlers to the 'copy code' buttons - const buttons = ReactDOM.findDOMNode(this).getElementsByClassName("mx_EventTile_copyButton"); - for (let i = 0; i < buttons.length; i++) { - buttons[i].onclick = (e) => { - const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; + + // Add 'copy' buttons to pre blocks + ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre').forEach((p) => { + const button = document.createElement("span"); + button.className = "mx_EventTile_copyButton"; + button.onclick = (e) => { + const copyCode = button.parentNode.getElementsByTagName("code")[0]; this.copyToClipboard(copyCode.textContent); }; - } + p.appendChild(button); + }); } }, From 05a986334d482ecd37af40c4769700fe54fdcb46 Mon Sep 17 00:00:00 2001 From: David Baker Date: Sun, 10 Sep 2017 15:58:17 +0100 Subject: [PATCH 2/2] Separate function to add code copy button For neatness and also so it can show up separately in the profiler. --- src/components/views/messages/TextualBody.js | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 3937780c2a..a58422e840 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -114,16 +114,7 @@ module.exports = React.createClass({ }, 10); } - // Add 'copy' buttons to pre blocks - ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre').forEach((p) => { - const button = document.createElement("span"); - button.className = "mx_EventTile_copyButton"; - button.onclick = (e) => { - const copyCode = button.parentNode.getElementsByTagName("code")[0]; - this.copyToClipboard(copyCode.textContent); - }; - p.appendChild(button); - }); + this._addCodeCopyButton(); } }, @@ -260,6 +251,19 @@ module.exports = React.createClass({ } }, + _addCodeCopyButton() { + // Add 'copy' buttons to pre blocks + ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre').forEach((p) => { + const button = document.createElement("span"); + button.className = "mx_EventTile_copyButton"; + button.onclick = (e) => { + const copyCode = button.parentNode.getElementsByTagName("code")[0]; + this.copyToClipboard(copyCode.textContent); + }; + p.appendChild(button); + }); + }, + onCancelClick: function(event) { this.setState({ widgetHidden: true }); // FIXME: persist this somewhere smarter than local storage