From f991948c4931ecf2d4e32dadc8b099207f76fa82 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 19 Mar 2022 16:04:33 +0000 Subject: [PATCH] Started initial tasklist attempt, failed implementation --- resources/js/wysiwyg/config.js | 5 +- resources/js/wysiwyg/plugins-tasklist.js | 123 +++++++++++++++++++++++ resources/sass/_text.scss | 1 + 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 resources/js/wysiwyg/plugins-tasklist.js diff --git a/resources/js/wysiwyg/config.js b/resources/js/wysiwyg/config.js index 965b14d08..fab6a3886 100644 --- a/resources/js/wysiwyg/config.js +++ b/resources/js/wysiwyg/config.js @@ -10,6 +10,7 @@ import {getPlugin as getCustomhrPlugin} from "./plugins-customhr"; import {getPlugin as getImagemanagerPlugin} from "./plugins-imagemanager"; import {getPlugin as getAboutPlugin} from "./plugins-about"; import {getPlugin as getDetailsPlugin} from "./plugins-details"; +import {getPlugin as getTasklistPlugin} from "./plugins-tasklist"; const style_formats = [ {title: "Large Header", format: "h2", preview: 'color: blue;'}, @@ -81,6 +82,7 @@ function gatherPlugins(options) { "imagemanager", "about", "details", + "tasklist", options.textDirection === 'rtl' ? 'directionality' : '', ]; @@ -89,6 +91,7 @@ function gatherPlugins(options) { window.tinymce.PluginManager.add('imagemanager', getImagemanagerPlugin(options)); window.tinymce.PluginManager.add('about', getAboutPlugin(options)); window.tinymce.PluginManager.add('details', getDetailsPlugin(options)); + window.tinymce.PluginManager.add('tasklist', getTasklistPlugin(options)); if (options.drawioUrl) { window.tinymce.PluginManager.add('drawio', getDrawioPlugin(options)); @@ -204,7 +207,7 @@ export function build(options) { statusbar: false, menubar: false, paste_data_images: false, - extended_valid_elements: 'pre[*],svg[*],div[drawio-diagram],details[*],summary[*],div[*]', + extended_valid_elements: 'pre[*],svg[*],div[drawio-diagram],details[*],summary[*],div[*],li[class]', automatic_uploads: false, custom_elements: 'doc-root,code-block', valid_children: [ diff --git a/resources/js/wysiwyg/plugins-tasklist.js b/resources/js/wysiwyg/plugins-tasklist.js new file mode 100644 index 000000000..07f934463 --- /dev/null +++ b/resources/js/wysiwyg/plugins-tasklist.js @@ -0,0 +1,123 @@ +/** + * @param {Editor} editor + */ +function defineTaskListCustomElement(editor) { + const doc = editor.getDoc(); + const win = doc.defaultView; + + class TaskListElement extends win.HTMLElement { + constructor() { + super(); + // this.attachShadow({mode: 'open'}); + // + // const input = doc.createElement('input'); + // input.setAttribute('type', 'checkbox'); + // input.setAttribute('disabled', 'disabled'); + // + // if (this.hasAttribute('selected')) { + // input.setAttribute('selected', 'selected'); + // } + // + // this.shadowRoot.append(input); + // this.shadowRoot.close(); + } + } + + win.customElements.define('task-list-item', TaskListElement); +} + +/** + * @param {Editor} editor + * @param {String} url + */ +function register(editor, url) { + + // editor.on('NewBlock', ({ newBlock}) => { + // ensureElementHasCheckbox(newBlock); + // }); + + editor.on('PreInit', () => { + + defineTaskListCustomElement(editor); + + editor.parser.addNodeFilter('li', function(elms) { + for (const elem of elms) { + if (elem.attributes.map.class === 'task-list-item') { + replaceTaskListNode(elem); + } + } + }); + + // editor.serializer.addNodeFilter('li', function(elms) { + // for (const elem of elms) { + // if (elem.attributes.map.class === 'task-list-item') { + // ensureNodeHasCheckbox(elem); + // } + // } + // }); + + }); + +} + +/** + * @param {AstNode} node + */ +function replaceTaskListNode(node) { + + const taskListItem = new tinymce.html.Node.create('task-list-item', { + }); + + for (const child of node.children()) { + if (node.name !== 'input') { + taskListItem.append(child); + } + } + + node.replace(taskListItem); +} + +// /** +// * @param {Element} elem +// */ +// function ensureElementHasCheckbox(elem) { +// const hasCheckbox = elem.querySelector(':scope > input[type="checkbox"]') !== null; +// if (hasCheckbox) { +// return; +// } +// +// const input = elem.ownerDocument.createElement('input'); +// input.setAttribute('type', 'checkbox'); +// input.setAttribute('disabled', 'disabled'); +// elem.prepend(input); +// } + +/** + * @param {AstNode} elem + */ +function ensureNodeHasCheckbox(elem) { + // Stop if there's already an input + if (elem.firstChild && elem.firstChild.name === 'input') { + return; + } + + const input = new tinymce.html.Node.create('input', { + type: 'checkbox', + disabled: 'disabled', + }); + + if (elem.firstChild) { + elem.insert(input, elem.firstChild, true); + } else { + elem.append(input); + } +} + + +/** + * @param {WysiwygConfigOptions} options + * @return {register} + */ +export function getPlugin(options) { + return register; +} \ No newline at end of file diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index cbe3cd4be..884808bb4 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -310,6 +310,7 @@ li > ol, li > ul { } li.checkbox-item, li.task-list-item { + display: list-item; list-style: none; margin-left: -($-m * 1.2); input[type="checkbox"] {