diff --git a/app/assets/javascripts/discourse/lib/copy-text.js.es6 b/app/assets/javascripts/discourse/lib/copy-text.js.es6 new file mode 100644 index 00000000000..87303623397 --- /dev/null +++ b/app/assets/javascripts/discourse/lib/copy-text.js.es6 @@ -0,0 +1,34 @@ +/** + * Copy text to the clipboard. Must be called from within a user gesture (Chrome). + */ +export default function(text, element) { + let supported = false; + try { + // Chrome: This only returns true within a user gesture. + // Chrome: queryCommandEnabled() only returns true if a selection is + // present, so we use queryCommandSupported() instead for the fail-fast. + if (document.queryCommandSupported('copy')) { + supported = true; + } + } catch (e) { + // Ignore + } + if (!supported) { + return; + } + + let newRange = document.createRange(); + newRange.selectNode(element); + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(newRange); + + try { + if (document.execCommand("copy")) { + return true; + } + } catch (e) { + // Ignore + } + return false; +} diff --git a/app/assets/javascripts/discourse/templates/share.hbs b/app/assets/javascripts/discourse/templates/share.hbs index cdc48cfb581..5bd54e1d599 100644 --- a/app/assets/javascripts/discourse/templates/share.hbs +++ b/app/assets/javascripts/discourse/templates/share.hbs @@ -19,3 +19,4 @@ {{fa-icon "times-circle"}} {{/if}} + diff --git a/app/assets/javascripts/discourse/views/share.js.es6 b/app/assets/javascripts/discourse/views/share.js.es6 index ab052c2c5c2..91c9c89ae00 100644 --- a/app/assets/javascripts/discourse/views/share.js.es6 +++ b/app/assets/javascripts/discourse/views/share.js.es6 @@ -1,3 +1,5 @@ +import copyText from 'discourse/lib/copy-text'; + export default Discourse.View.extend({ templateName: 'share', elementId: 'share-link', @@ -18,34 +20,13 @@ export default Discourse.View.extend({ return null; }.property('controller.link'), - copyLink($element) { - const element = $element[0]; - try { - if (document.queryCommandSupported('copy')) { - let newRange = document.createRange(); - newRange.selectNode(element); - const selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(newRange); - - if (document.execCommand("copy")) { - this.set('controller.copied', true); - } - } - } catch (e) { - // Ignore - } - }, - linkChanged: function() { const self = this; - this.set('controller.copied', false); if (this.present('controller.link')) { Em.run.next(function() { if (!self.capabilities.touch) { var $linkInput = $('#share-link input'); $linkInput.val(self.get('controller.link')); - self.copyLink($linkInput); // Wait for the fade-in transition to finish before selecting the link: window.setTimeout(function() { @@ -55,7 +36,6 @@ export default Discourse.View.extend({ var $linkForTouch = $('#share-link .share-for-touch a'); $linkForTouch.attr('href',self.get('controller.link')); $linkForTouch.html(self.get('controller.link')); - self.copyLink($linkForTouch); } }); } @@ -83,6 +63,7 @@ export default Discourse.View.extend({ var $currentTarget = $(e.currentTarget), $currentTargetOffset = $currentTarget.offset(), $shareLink = $('#share-link'), + copyElement = document.getElementById('copy-target'), url = $currentTarget.data('share-url'), postNumber = $currentTarget.data('post-number'), date = $currentTarget.children().data('time'); @@ -113,10 +94,18 @@ export default Discourse.View.extend({ $shareLink.css({left: "" + x + "px"}); } + self.set('controller.copied', false); + + const copySuccess = copyText(url, copyElement); + self.set('controller.link', url); self.set('controller.postNumber', postNumber); self.set('controller.date', date); + Ember.run.later(null, function() { + self.set('controller.copied', copySuccess); + }, 50); + return false; });