diff --git a/src/js/editor/editor.js b/src/js/editor/editor.js index c5df579fe..8647005d1 100644 --- a/src/js/editor/editor.js +++ b/src/js/editor/editor.js @@ -201,7 +201,7 @@ class Editor { mergeWithOptions(this, defaults, options); this._parser = PostParser; - this._renderer = new Renderer(this.cards, this.unknownCardHandler, this.cardOptions); + this._renderer = new Renderer(this, this.cards, this.unknownCardHandler, this.cardOptions); this.applyClassName(); this.applyPlaceholder(); @@ -428,6 +428,10 @@ class Editor { } } + didUpdate() { + this.trigger('update'); + } + getActiveMarkers() { const cursor = this.cursor; return cursor.activeMarkers; diff --git a/src/js/models/card-node.js b/src/js/models/card-node.js index a5997fd5a..76bef3090 100644 --- a/src/js/models/card-node.js +++ b/src/js/models/card-node.js @@ -1,5 +1,6 @@ export default class CardNode { - constructor(card, section, element, cardOptions) { + constructor(editor, card, section, element, cardOptions) { + this.editor = editor; this.card = card; this.section = section; this.cardOptions = cardOptions; @@ -29,6 +30,8 @@ export default class CardNode { edit: () => { this.edit(); }, save: (payload) => { this.section.payload = payload; + + this.editor.didUpdate(); this.display(); }, cancel: () => { this.display(); } diff --git a/src/js/renderers/editor-dom.js b/src/js/renderers/editor-dom.js index 2271b0f0d..c9e5b6083 100644 --- a/src/js/renderers/editor-dom.js +++ b/src/js/renderers/editor-dom.js @@ -87,7 +87,8 @@ function renderMarker(marker, element, previousRenderNode) { } class Visitor { - constructor(cards, unknownCardHandler, options) { + constructor(editor, cards, unknownCardHandler, options) { + this.editor = editor; this.cards = cards; this.unknownCardHandler = unknownCardHandler; this.options = options; @@ -160,6 +161,7 @@ class Visitor { } [CARD_TYPE](renderNode, section) { + const {editor, options} = this; const card = detect(this.cards, card => card.name === section.name); const env = { name: section.name }; @@ -169,11 +171,11 @@ class Visitor { renderNode.parentNode.element.appendChild(renderNode.element); if (card) { - let cardNode = new CardNode(card, section, renderNode.element, this.options); + let cardNode = new CardNode(editor, card, section, renderNode.element, options); renderNode.cardNode = cardNode; cardNode.display(); } else { - this.unknownCardHandler(renderNode.element, this.options, env, section.payload); + this.unknownCardHandler(renderNode.element, options, env, section.payload); } } } @@ -254,8 +256,9 @@ function lookupNode(renderTree, parentNode, postNode, previousNode) { } export default class Renderer { - constructor(cards, unknownCardHandler, options) { - this.visitor = new Visitor(cards, unknownCardHandler, options); + constructor(editor, cards, unknownCardHandler, options) { + this.editor = editor; + this.visitor = new Visitor(editor, cards, unknownCardHandler, options); this.nodes = []; } diff --git a/tests/acceptance/basic-editor-test.js b/tests/acceptance/basic-editor-test.js index a840e7517..f061c889a 100644 --- a/tests/acceptance/basic-editor-test.js +++ b/tests/acceptance/basic-editor-test.js @@ -1,11 +1,10 @@ import { Editor } from 'content-kit-editor'; -import Helpers from '../test-helpers'; const { test, module } = QUnit; let fixture, editor, editorElement; -module('Acceptance: basic editor', { +module('Acceptance: editor: basic', { beforeEach() { fixture = document.getElementById('qunit-fixture'); editorElement = document.createElement('div'); @@ -13,7 +12,9 @@ module('Acceptance: basic editor', { fixture.appendChild(editorElement); }, afterEach() { - editor.destroy(); + if (editor) { + editor.destroy(); + } } }); @@ -28,17 +29,3 @@ test('sets element as contenteditable', (assert) => { assert.equal(editorElement.firstChild.tagName, 'P', `editor element has a P as its first child`); }); - -test('editing element changes editor post model', (assert) => { - let innerHTML = `
Hello
`; - editorElement.innerHTML = innerHTML; - editor = new Editor(document.getElementById('editor')); - - let p = editorElement.querySelector('p'); - let textElement = p.firstChild; - - Helpers.dom.moveCursorTo(textElement, 0); - - document.execCommand('insertText', false, 'A'); - assert.equal(p.textContent, 'AHello'); -}); diff --git a/tests/acceptance/editor-cards-test.js b/tests/acceptance/editor-cards-test.js new file mode 100644 index 000000000..12613f8cb --- /dev/null +++ b/tests/acceptance/editor-cards-test.js @@ -0,0 +1,84 @@ +import { Editor } from 'content-kit-editor'; +import Helpers from '../test-helpers'; +import { MOBILEDOC_VERSION } from 'content-kit-editor/renderers/mobiledoc'; + +const { test, module } = QUnit; + +let fixture, editor, editorElement; + +const mobiledoc = { + version: MOBILEDOC_VERSION, + sections: [ + [], + [ + [10, 'simple-card'] + ] + ] +}; + +const simpleCard = { + name: 'simple-card', + display: { + setup(element, options, env) { + let button = document.createElement('button'); + button.setAttribute('id', 'display-button'); + element.appendChild(button); + button.onclick = env.edit; + return {button}; + }, + teardown({button}) { + button.parentNode.removeChild(button); + } + }, + edit: { + setup(element, options, env) { + let button = document.createElement('button'); + button.setAttribute('id', 'edit-button'); + button.onclick = env.save; + element.appendChild(button); + return {button}; + }, + teardown({button}) { + button.parentNode.removeChild(button); + } + } +}; + +module('Acceptance: editor: cards', { + beforeEach() { + fixture = document.getElementById('qunit-fixture'); + editorElement = document.createElement('div'); + editorElement.setAttribute('id', 'editor'); + fixture.appendChild(editorElement); + }, + afterEach() { + if (editor) { + editor.destroy(); + } + } +}); + +test('changing to display state triggers update on editor', (assert) => { + const cards = [simpleCard]; + editor = new Editor(editorElement, {mobiledoc, cards}); + + let updateCount = 0, + triggeredUpdate = () => updateCount++; + editor.on('update', triggeredUpdate); + + let displayButton = document.getElementById('display-button'); + assert.ok(!!displayButton, 'precond - display button is there'); + + Helpers.dom.triggerEvent(displayButton, 'click'); + + let editButton = document.getElementById('edit-button'); + assert.ok(!!editButton, 'precond - edit button is there after clicking the display button'); + + let currentUpdateCount = updateCount; + + Helpers.dom.triggerEvent(editButton, 'click'); + + assert.equal(updateCount, currentUpdateCount+1, + 'update is triggered after switching to display mode'); +}); + diff --git a/tests/unit/renderers/editor-dom-test.js b/tests/unit/renderers/editor-dom-test.js index 88274ab06..0af46e402 100644 --- a/tests/unit/renderers/editor-dom-test.js +++ b/tests/unit/renderers/editor-dom-test.js @@ -8,11 +8,12 @@ const DATA_URL = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAAC let builder; function render(renderTree, cards=[]) { - let renderer = new Renderer(cards); + let editor = {}; + let renderer = new Renderer(editor, cards); return renderer.render(renderTree); } -module("Unit: Renderer", { +module("Unit: Renderer: Editor-Dom", { beforeEach() { builder = generateBuilder(); }