diff --git a/README.md b/README.md index 16dc15a6f..2ff18ff1f 100644 --- a/README.md +++ b/README.md @@ -225,11 +225,14 @@ The available lifecycle hooks are: movement or clicking in the document. * `editor.onTextInput()` - When the user adds text to the document (see [example](https://github.com/bustlelabs/mobiledoc-kit#responding-to-text-input)) * `editor.inputModeDidChange()` - The active section(s) or markup(s) at the current cursor position or selection have changed. This hook can be used with `Editor#activeMarkups`, `Editor#activeSections`, and `Editor#activeSectionAttributes` to implement a custom toolbar. -* `editor.beforeToggleMarkup(({markup, range, willAdd} => {...})` - Register a +* `editor.beforeToggleMarkup(({markup, range, willAdd}) => {...})` - Register a callback that will be called before `editor#toggleMarkup` is applied. If any callback returns literal `false`, the toggling of markup will be canceled. (Toggling markup done via the postEditor, e.g. `editor.run(postEditor => postEditor.toggleMarkup(...))` will skip this callback. +* `editor.willCopy(({html, text, mobiledoc}) => {...})` - Called before the + serialized versions of the selected markup is copied to the system + pasteboard. For more details on the lifecycle hooks, see the [Editor documentation](https://bustle.github.io/mobiledoc-kit/demo/docs/Editor.html). diff --git a/src/js/editor/editor.js b/src/js/editor/editor.js index f3e2fd586..54a699924 100644 --- a/src/js/editor/editor.js +++ b/src/js/editor/editor.js @@ -70,7 +70,8 @@ const CALLBACK_QUEUES = { CURSOR_DID_CHANGE: 'cursorDidChange', DID_REPARSE: 'didReparse', POST_DID_CHANGE: 'postDidChange', - INPUT_MODE_DID_CHANGE: 'inputModeDidChange' + INPUT_MODE_DID_CHANGE: 'inputModeDidChange', + WILL_COPY: 'willCopy' }; /** @@ -812,6 +813,10 @@ class Editor { this.addCallback(CALLBACK_QUEUES.DID_RENDER, callback); } + willCopy(callback) { + this.addCallback(CALLBACK_QUEUES.WILL_COPY, callback); + } + /** * @param {Function} callback This callback will be called before deleting. * @public diff --git a/src/js/editor/event-manager.js b/src/js/editor/event-manager.js index c4c44484e..6671f7805 100644 --- a/src/js/editor/event-manager.js +++ b/src/js/editor/event-manager.js @@ -229,6 +229,8 @@ export default class EventManager { mobiledoc: editor.serializePost(post, 'mobiledoc') }; + editor.runCallbacks('willCopy', [data]); + setClipboardData(event, data, window); } diff --git a/tests/acceptance/editor-copy-paste-test.js b/tests/acceptance/editor-copy-paste-test.js index 3de6cbfac..bfd0785c3 100644 --- a/tests/acceptance/editor-copy-paste-test.js +++ b/tests/acceptance/editor-copy-paste-test.js @@ -123,6 +123,25 @@ test('paste plain text into an empty Mobiledoc', (assert) => { assert.hasElement('#editor p:contains(abc)', 'pastes the text'); }); +test('willCopy callback called before copy', (assert) => { + const mobiledoc = Helpers.mobiledoc.build( + ({post, markupSection, marker}) => { + return post([markupSection('p', [marker('abc')])]); + }); + editor = new Editor({mobiledoc}); + editor.addCallback('willCopy', data => { + assert.deepEqual(data.mobiledoc, mobiledoc); + data.mobiledoc.sections[0][1] = 'blockquote'; + console.log({ data }) + }); + editor.render(editorElement); + + assert.hasElement('#editor p:contains(abc)', 'precond - has p'); + + Helpers.dom.selectText(editor, 'abc', editorElement); + Helpers.dom.triggerCopyEvent(editor); +}); + test('can cut and then paste content', (assert) => { const mobiledoc = Helpers.mobiledoc.build( ({post, markupSection, marker}) => {