diff --git a/resources/js/components/markdown-editor.js b/resources/js/components/markdown-editor.js index c89a7ad8b..de256a846 100644 --- a/resources/js/components/markdown-editor.js +++ b/resources/js/components/markdown-editor.js @@ -30,6 +30,12 @@ class MarkdownEditor { this.displayDoc = this.display.contentDocument; this.init(); }); + + window.$events.emitPublic(elem, 'editor-markdown::setup', { + markdownIt: this.markdown, + displayEl: this.display, + codeMirrorInstance: this.cm, + }); } init() { diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index c03c0d2aa..60a6743ea 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -412,6 +412,7 @@ class WysiwygEditor { this.loadPlugins(); this.tinyMceConfig = this.getTinyMceConfig(); + window.$events.emitPublic(elem, 'editor-tinymce::pre-init', {config: this.tinyMceConfig}); window.tinymce.init(this.tinyMceConfig); } @@ -654,6 +655,8 @@ class WysiwygEditor { // Paste image-uploads editor.on('paste', event => editorPaste(event, editor, context)); + // Custom handler hook + window.$events.emitPublic(context.elem, 'editor-tinymce::setup', {editor}); } }; } diff --git a/resources/js/services/code.js b/resources/js/services/code.js index 1e0e48289..ca66bdb5a 100644 --- a/resources/js/services/code.js +++ b/resources/js/services/code.js @@ -240,24 +240,27 @@ function setContent(cmInstance, codeContent) { } /** - * Get a CodeMirror instace to use for the markdown editor. + * Get a CodeMirror instance to use for the markdown editor. * @param {HTMLElement} elem * @returns {*} */ function markdownEditor(elem) { - let content = elem.textContent; - - return CodeMirror(function (elt) { - elem.parentNode.insertBefore(elt, elem); - elem.style.display = 'none'; - }, { + const content = elem.textContent; + const config = { value: content, mode: "markdown", lineNumbers: true, theme: getTheme(), lineWrapping: true, scrollPastEnd: true, - }); + }; + + window.$events.emitPublic(elem, 'editor-markdown-cm::pre-init', {config}); + + return CodeMirror(function (elt) { + elem.parentNode.insertBefore(elt, elem); + elem.style.display = 'none'; + }, config); } /** diff --git a/resources/js/services/events.js b/resources/js/services/events.js index 1f97d0cb8..fa3ed7fdf 100644 --- a/resources/js/services/events.js +++ b/resources/js/services/events.js @@ -7,6 +7,12 @@ class Events { this.stack = []; } + /** + * Emit a custom event for any handlers to pick-up. + * @param {String} eventName + * @param {*} eventData + * @returns {Events} + */ emit(eventName, eventData) { this.stack.push({name: eventName, data: eventData}); if (typeof this.listeners[eventName] === 'undefined') return this; @@ -18,11 +24,32 @@ class Events { return this; } + /** + * Listen to a custom event and run the given callback when that event occurs. + * @param {String} eventName + * @param {Function} callback + * @returns {Events} + */ listen(eventName, callback) { if (typeof this.listeners[eventName] === 'undefined') this.listeners[eventName] = []; this.listeners[eventName].push(callback); return this; } + + /** + * Emit an event for public use. + * Sends the event via the native DOM event handling system. + * @param {Element} targetElement + * @param {String} eventName + * @param {Object} eventData + */ + emitPublic(targetElement, eventName, eventData) { + const event = new CustomEvent(eventName, { + detail: eventData, + bubbles: true + }); + targetElement.dispatchEvent(event); + } } export default Events; \ No newline at end of file