diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ 'names' => array( 'core.pkg.css' => 'fb144113', - 'core.pkg.js' => 'd3fecc57', + 'core.pkg.js' => 'e39d336b', 'darkconsole.pkg.js' => 'ca8671ce', 'differential.pkg.css' => 'cc216438', 'differential.pkg.js' => '11a5b750', @@ -463,7 +463,7 @@ 'rsrc/js/core/behavior-line-linker.js' => 'bc778103', 'rsrc/js/core/behavior-more.js' => '9b9197be', 'rsrc/js/core/behavior-object-selector.js' => 'b4eef37b', - 'rsrc/js/core/behavior-oncopy.js' => 'dab9253e', + 'rsrc/js/core/behavior-oncopy.js' => 'c3e218fe', 'rsrc/js/core/behavior-phabricator-nav.js' => 'b5842a5e', 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a', 'rsrc/js/core/behavior-refresh-csrf.js' => 'c4b31646', @@ -596,7 +596,7 @@ 'javelin-behavior-phabricator-nav' => 'b5842a5e', 'javelin-behavior-phabricator-notification-example' => 'c51a6616', 'javelin-behavior-phabricator-object-selector' => 'b4eef37b', - 'javelin-behavior-phabricator-oncopy' => 'dab9253e', + 'javelin-behavior-phabricator-oncopy' => 'c3e218fe', 'javelin-behavior-phabricator-remarkup-assist' => 'c021950a', 'javelin-behavior-phabricator-reveal-content' => '8f24abfc', 'javelin-behavior-phabricator-search-typeahead' => 'f6b56f7a', @@ -1634,6 +1634,11 @@ 2 => 'javelin-util', 3 => 'javelin-magical-init', ), + 'c3e218fe' => + array( + 0 => 'javelin-behavior', + 1 => 'javelin-dom', + ), 'c4b31646' => array( 0 => 'javelin-request', @@ -1768,11 +1773,6 @@ 1 => 'javelin-util', 2 => 'javelin-stratcom', ), - 'dab9253e' => - array( - 0 => 'javelin-behavior', - 1 => 'javelin-dom', - ), 'dd7e8ef5' => array( 0 => 'javelin-behavior', diff --git a/webroot/rsrc/js/core/behavior-oncopy.js b/webroot/rsrc/js/core/behavior-oncopy.js --- a/webroot/rsrc/js/core/behavior-oncopy.js +++ b/webroot/rsrc/js/core/behavior-oncopy.js @@ -18,63 +18,48 @@ var zws = "\u200B"; // Unicode Zero-Width Space - document.body.oncopy = function(e) { + JX.enableDispatch(document.body, 'copy'); + JX.Stratcom.listen( + ['copy'], + null, + function(e) { - var selection = window.getSelection(); - var text = selection.toString(); - - if (text.indexOf(zws) == -1) { - // If there's no marker in the text, just let it copy normally. - return; - } - - var result = []; - - // Strip everything before the marker (and the marker itself) out of the - // text. If a line doesn't have the marker, throw it away (the assumption - // is that it's a line number or part of some other meta-text). - var lines = text.split("\n"); - var pos; - for (var ii = 0; ii < lines.length; ii++) { - pos = lines[ii].indexOf(zws); - if (pos == -1 && ii !== 0) { - continue; + var selection; + var text; + if (window.getSelection) { + selection = window.getSelection(); + text = selection.toString(); + } else { + selection = document.selection; + text = selection.createRange().text; } - result.push(lines[ii].substring(pos + 1)); - } - result = result.join("\n"); - - if (e.clipboardData) { - // Safari and Chrome support this easy, straightforward mechanism. - e.clipboardData.setData('Text', result); - e.preventDefault(); - } else { - // In Firefox, we have to create a
 and select the text in it, then
-      // let the copy event fire. It has to be a 
 because Firefox won't
-      // copy returns properly out of a div, even if it has 'whitespace: pre'.
-      // There's been a bug open for 10 (!) years:
-      //
-      //   https://bugzilla.mozilla.org/show_bug.cgi?id=116083
-
-      var style = {
-        position: 'absolute',
-        left:     '-10000px'
-      };
-      var pre = JX.$N('pre', {style: style}, result);
-      document.body.appendChild(pre);
+      if (text.indexOf(zws) == -1) {
+        // If there's no marker in the text, just let it copy normally.
+        return;
+      }
 
-      // Select the text in the 
.
-      var range = document.createRange();
-      range.selectNodeContents(pre);
-      selection.removeAllRanges();
-      selection.addRange(range);
+      var result = [];
 
-      setTimeout(function() { JX.DOM.remove(pre); }, 0);
+      // Strip everything before the marker (and the marker itself) out of the
+      // text. If a line doesn't have the marker, throw it away (the assumption
+      // is that it's a line number or part of some other meta-text).
+      var lines = text.split("\n");
+      var pos;
+      for (var ii = 0; ii < lines.length; ii++) {
+        pos = lines[ii].indexOf(zws);
+        if (pos == -1 && ii !== 0) {
+          continue;
+        }
+        result.push(lines[ii].substring(pos + 1));
+      }
+      result = result.join("\n");
 
-      // TODO: I tried to restore the old selection range but it doesn't seem
-      // to work or give me any errors. So you lose your selection when you
-      // copy. Oh well?
-    }
-  };
+      var rawEvent = e.getRawEvent();
+      var clipboardData = 'clipboardData' in rawEvent ?
+        rawEvent.clipboardData :
+        window.clipboardData;
+      clipboardData.setData('Text', result);
+      e.prevent();
+    });
 });