From 3556155332342e99df475e5eb7310e288418a9a6 Mon Sep 17 00:00:00 2001 From: Cory Forsyth Date: Mon, 2 Nov 2015 17:02:43 -0500 Subject: [PATCH] Enable pasting html and text externally Sets the "text/html" and "text/plain" clipboard data on copy and cut events. fixes #180 --- src/js/utils/paste-utils.js | 12 ++++---- src/js/utils/selection-utils.js | 13 ++++++++- tests/acceptance/editor-copy-paste-test.js | 33 ++++++++++++++++++++++ tests/helpers/dom.js | 7 ++++- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/js/utils/paste-utils.js b/src/js/utils/paste-utils.js index 4f93be1ab..61d2cb06b 100644 --- a/src/js/utils/paste-utils.js +++ b/src/js/utils/paste-utils.js @@ -1,9 +1,8 @@ /* global JSON */ import MobiledocParser from '../parsers/mobiledoc'; import HTMLParser from '../parsers/html'; - -// FIXME fix this issue: -const issueUrl = 'https://github.com/bustlelabs/content-kit-editor/issues/180'; +import { createDiv } from '../utils/element-utils'; +import { getSelectionContents } from '../utils/selection-utils'; export function setClipboardCopyData(copyEvent, editor) { const { cursor, post } = editor; @@ -11,11 +10,14 @@ export function setClipboardCopyData(copyEvent, editor) { const range = cursor.offsets; const mobiledoc = post.cloneRange(range); + const fragment = getSelectionContents(); + const div = createDiv(); + div.appendChild(fragment); const html = `
` + - `Pasting from Content-Kit not yet supported.` + + div.innerHTML + `
`; - const plain = `Pasting from Content-Kit not yet supported. (${issueUrl})`; + const plain = div.textContent; clipboardData.setData('text/plain', plain); clipboardData.setData('text/html', html); diff --git a/src/js/utils/selection-utils.js b/src/js/utils/selection-utils.js index fabcc5d7f..826edc41b 100644 --- a/src/js/utils/selection-utils.js +++ b/src/js/utils/selection-utils.js @@ -5,6 +5,16 @@ function clearSelection() { window.getSelection().removeAllRanges(); } +// @return {DocumentFragment} +function getSelectionContents() { + let selection = window.getSelection(); + if (selection.rangeCount > 0) { + return selection.getRangeAt(0).cloneContents(); + } else { + return document.createDocumentFragment(); + } +} + function comparePosition(selection) { let { anchorNode, focusNode, anchorOffset, focusOffset } = selection; let headNode, tailNode, headOffset, tailOffset; @@ -37,5 +47,6 @@ export { restoreRange, containsNode, clearSelection, - comparePosition + comparePosition, + getSelectionContents }; diff --git a/tests/acceptance/editor-copy-paste-test.js b/tests/acceptance/editor-copy-paste-test.js index 9c76881d4..71d3972b6 100644 --- a/tests/acceptance/editor-copy-paste-test.js +++ b/tests/acceptance/editor-copy-paste-test.js @@ -210,3 +210,36 @@ test('copy-paste can copy list sections', (assert) => { assert.equal($('#editor ul').length, 2, 'pastes the list'); assert.hasElement($('#editor ul:eq(0) li:contains(list)')); }); + +test('copy sets html & text for pasting externally', (assert) => { + const mobiledoc = Helpers.mobiledoc.build( + ({post, markupSection, marker}) => { + return post([ + markupSection('h1', [marker('h1 heading')]), + markupSection('h2', [marker('h2 subheader')]), + markupSection('p', [marker('The text')]) + ]); + }); + editor = new Editor({mobiledoc}); + editor.render(editorElement); + + Helpers.dom.selectText('heading', editor.element, + 'The text', editor.element); + + Helpers.dom.triggerCopyEvent(editor); + + let text = Helpers.dom.getCopyData('text/plain'); + let html = Helpers.dom.getCopyData('text/html'); + assert.equal(text, [ + "heading", + "h2 subheader", + "The text" + ].join(''), 'gets plain text'); + + assert.ok(html.indexOf("

heading") !== -1, + 'html has h1'); + assert.ok(html.indexOf("

h2 subheader") !== -1, + 'html has h2'); + assert.ok(html.indexOf("

The text") !== -1, + 'html has p'); +}); diff --git a/tests/helpers/dom.js b/tests/helpers/dom.js index a8633ce91..365d98be0 100644 --- a/tests/helpers/dom.js +++ b/tests/helpers/dom.js @@ -211,6 +211,10 @@ function triggerPasteEvent(editor) { editor.triggerEvent(editor.element, 'paste', event); } +function getCopyData(type) { + return lastCopyData[type]; +} + function fromHTML(html) { html = $.trim(html); let div = document.createElement('div'); @@ -237,7 +241,8 @@ const DOMHelper = { triggerRightArrowKey, triggerCopyEvent, triggerCutEvent, - triggerPasteEvent + triggerPasteEvent, + getCopyData }; export { triggerEvent };