1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 19:40:55 +01:00

Simplify oncopy behavior

Summary:
Firefox has supported clipboardData since version 22 (Jul 2013), and even IE8 supports it if you look at `window.clipboardData` instead of `e.clipboardData`. As a result, we can simplify this code significantly.

I also used (or at least, attempted to) Javelin so that we can get the event object and preventDefault more easily. Plus, this way we don't assign to document.body.oncopy.

Test Plan: Copied a selection including a line number in Chrome, Firefox, and IE8. The line number didn't get copied.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, Korvin

Differential Revision: https://secure.phabricator.com/D8688
This commit is contained in:
Ben Alpert 2014-04-03 09:20:55 -07:00 committed by epriestley
parent 3e6bfda0ca
commit 26c836e1e1
2 changed files with 46 additions and 61 deletions

View file

@ -8,7 +8,7 @@ return array(
'names' => 'names' =>
array( array(
'core.pkg.css' => 'fb144113', 'core.pkg.css' => 'fb144113',
'core.pkg.js' => 'd3fecc57', 'core.pkg.js' => 'e39d336b',
'darkconsole.pkg.js' => 'ca8671ce', 'darkconsole.pkg.js' => 'ca8671ce',
'differential.pkg.css' => 'cc216438', 'differential.pkg.css' => 'cc216438',
'differential.pkg.js' => '11a5b750', 'differential.pkg.js' => '11a5b750',
@ -463,7 +463,7 @@ return array(
'rsrc/js/core/behavior-line-linker.js' => 'bc778103', 'rsrc/js/core/behavior-line-linker.js' => 'bc778103',
'rsrc/js/core/behavior-more.js' => '9b9197be', 'rsrc/js/core/behavior-more.js' => '9b9197be',
'rsrc/js/core/behavior-object-selector.js' => 'b4eef37b', '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-nav.js' => 'b5842a5e',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a', 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a',
'rsrc/js/core/behavior-refresh-csrf.js' => 'c4b31646', 'rsrc/js/core/behavior-refresh-csrf.js' => 'c4b31646',
@ -596,7 +596,7 @@ return array(
'javelin-behavior-phabricator-nav' => 'b5842a5e', 'javelin-behavior-phabricator-nav' => 'b5842a5e',
'javelin-behavior-phabricator-notification-example' => 'c51a6616', 'javelin-behavior-phabricator-notification-example' => 'c51a6616',
'javelin-behavior-phabricator-object-selector' => 'b4eef37b', '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-remarkup-assist' => 'c021950a',
'javelin-behavior-phabricator-reveal-content' => '8f24abfc', 'javelin-behavior-phabricator-reveal-content' => '8f24abfc',
'javelin-behavior-phabricator-search-typeahead' => 'f6b56f7a', 'javelin-behavior-phabricator-search-typeahead' => 'f6b56f7a',
@ -1634,6 +1634,11 @@ return array(
2 => 'javelin-util', 2 => 'javelin-util',
3 => 'javelin-magical-init', 3 => 'javelin-magical-init',
), ),
'c3e218fe' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'c4b31646' => 'c4b31646' =>
array( array(
0 => 'javelin-request', 0 => 'javelin-request',
@ -1768,11 +1773,6 @@ return array(
1 => 'javelin-util', 1 => 'javelin-util',
2 => 'javelin-stratcom', 2 => 'javelin-stratcom',
), ),
'dab9253e' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'dd7e8ef5' => 'dd7e8ef5' =>
array( array(
0 => 'javelin-behavior', 0 => 'javelin-behavior',

View file

@ -18,63 +18,48 @@ JX.behavior('phabricator-oncopy', function() {
var zws = "\u200B"; // Unicode Zero-Width Space 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 selection;
var text = selection.toString(); var text;
if (window.getSelection) {
if (text.indexOf(zws) == -1) { selection = window.getSelection();
// If there's no marker in the text, just let it copy normally. text = selection.toString();
return; } else {
} selection = document.selection;
text = selection.createRange().text;
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;
} }
result.push(lines[ii].substring(pos + 1));
}
result = result.join("\n");
if (e.clipboardData) { if (text.indexOf(zws) == -1) {
// Safari and Chrome support this easy, straightforward mechanism. // If there's no marker in the text, just let it copy normally.
e.clipboardData.setData('Text', result); return;
e.preventDefault(); }
} else {
// In Firefox, we have to create a <pre> and select the text in it, then var result = [];
// let the copy event fire. It has to be a <pre> 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 = { // Strip everything before the marker (and the marker itself) out of the
position: 'absolute', // text. If a line doesn't have the marker, throw it away (the assumption
left: '-10000px' // is that it's a line number or part of some other meta-text).
}; var lines = text.split("\n");
var pre = JX.$N('pre', {style: style}, result); var pos;
document.body.appendChild(pre); 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");
// Select the text in the <pre>. var rawEvent = e.getRawEvent();
var range = document.createRange(); var clipboardData = 'clipboardData' in rawEvent ?
range.selectNodeContents(pre); rawEvent.clipboardData :
selection.removeAllRanges(); window.clipboardData;
selection.addRange(range); clipboardData.setData('Text', result);
e.prevent();
setTimeout(function() { JX.DOM.remove(pre); }, 0); });
// 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?
}
};
}); });