Skip to content

Commit

Permalink
Always use native copy and cut
Browse files Browse the repository at this point in the history
Removes an optimization that stores and applies a delta when able. Since
we do not know where the copied or cut content will be pasted we always
need to fill in text/plain and text/html. When the browser fills these
in they get rid of our application/json clipboard data.

Fixes #785
  • Loading branch information
jhchen committed Jul 7, 2016
1 parent 7cc1683 commit eb2709f
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 74 deletions.
50 changes: 5 additions & 45 deletions modules/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ class Clipboard extends Module {
options.matchers = Clipboard.DEFAULTS.matchers.concat(options.matchers);
}
super(quill, options);
this.quill.root.addEventListener('copy', this.onCopy.bind(this));
this.quill.root.addEventListener('cut', this.onCut.bind(this));
this.quill.root.addEventListener('paste', this.onPaste.bind(this));
this.container = this.quill.addContainer('ql-clipboard');
this.container.setAttribute('contenteditable', true);
Expand Down Expand Up @@ -111,58 +109,20 @@ class Clipboard extends Module {
return delta;
}

onCopy(e) {
let range = this.quill.getSelection();
if (range == null || range.length === 0 || e.defaultPrevented) return;
let clipboard = e.clipboardData || window.clipboardData;
clipboard.setData('text', this.quill.getText(range));
// Only Chrome allows this shortcut, IE11 errors for trying
if (e.clipboardData) {
clipboard.setData('application/json', JSON.stringify(this.quill.getContents(range)));
}
// e.preventDefault();
}

onCut(e) {
if (e.defaultPrevented) return;
this.onCopy(e);
let range = this.quill.getSelection();
this.quill.deleteText(range, Quill.sources.USER);
this.quill.setSelection(range.index, Quill.sources.SILENT);
}

onPaste(e) {
if (e.defaultPrevented) return;
let range = this.quill.getSelection();
let clipboard = e.clipboardData || window.clipboardData;
let delta = new Delta().retain(range.index).delete(range.length);
let done = (delta) => {
this.container.focus();
setTimeout(() => {
let html = this.container.innerHTML;
delta = delta.concat(this.convert());
this.quill.updateContents(delta, Quill.sources.USER);
// range.length contributes to delta.length()
this.quill.setSelection(delta.length() - range.length, Quill.sources.SILENT);
this.quill.selection.scrollIntoView();
};
let intercept = (delta, callback) => {
this.container.focus();
setTimeout(() => {
let html = this.container.innerHTML;
delta = delta.concat(this.convert());
callback(delta);
}, 1);
};
// Firefox types is an iterable, not array
// IE11 types can be null
if ([].indexOf.call(clipboard.types || [], 'application/json') > -1) {
try {
let pasteJSON = JSON.parse(clipboard.getData('application/json'));
done(delta.concat(pasteJSON));
} catch(err) {
intercept(delta, done);
}
e.preventDefault();
} else {
intercept(delta, done);
}
}, 1);
}
}
Clipboard.DEFAULTS = {
Expand Down
30 changes: 1 addition & 29 deletions test/unit/modules/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,7 @@ describe('Clipboard', function() {
this.quill.setSelection(2, 5);
});

it('copy', function() {
spyOn(this.event.clipboardData, 'setData');
this.quill.clipboard.onCopy(this.event);
let jsonString = JSON.stringify(this.quill.getContents(2, 5));
let text = this.quill.getText(2, 5);
expect(this.event.clipboardData.setData).toHaveBeenCalledWith('application/json', jsonString);
expect(this.event.clipboardData.setData).toHaveBeenCalledWith('text', text);
});

it('cut', function() {
spyOn(this.event.clipboardData, 'setData');
let text = this.quill.getText(2, 5);
this.quill.clipboard.onCut(this.event);
expect(this.event.clipboardData.setData).toHaveBeenCalledWith('text', text);
expect(this.quill.root).toEqualHTML('<h1>01<em>7</em>8</h1>');
expect(this.quill.getSelection()).toEqual(new Range(2));
});

it('paste delta', function() {
let jsonString = JSON.stringify(new Delta().insert('|', { bold: true }));
this.event.clipboardData.types = ['text', 'application/json'];
spyOn(this.event.clipboardData, 'getData').and.returnValue(jsonString);
this.quill.clipboard.onPaste(this.event);
expect(this.quill.root).toEqualHTML('<h1>01<strong>|</strong><em>7</em>8</h1>');
expect(this.event.clipboardData.getData).toHaveBeenCalledWith('application/json');
expect(this.quill.getSelection()).toEqual(new Range(3));
});

it('paste from external', function(done) {
it('paste', function(done) {
this.event.clipboardData.types = ['text'];
spyOn(this.event.clipboardData, 'getData').and.returnValue('|');
this.quill.clipboard.container.innerHTML = '<strong>|</strong>';
Expand Down

0 comments on commit eb2709f

Please sign in to comment.