From ea62fe6004b2403c245d02a0b957f29d9c232ccd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 22 Mar 2022 14:03:20 +0000 Subject: [PATCH] Improved tasklist wysiwyg behaviour - Updated buttons/actions to better handle nesting. - Added hack for better usage with normal bullets --- resources/js/wysiwyg/plugins-tasklist.js | 30 ++++++++++++++++++++---- resources/js/wysiwyg/toolbars.js | 4 ++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/resources/js/wysiwyg/plugins-tasklist.js b/resources/js/wysiwyg/plugins-tasklist.js index cb1bb4a7a..2dd6528e1 100644 --- a/resources/js/wysiwyg/plugins-tasklist.js +++ b/resources/js/wysiwyg/plugins-tasklist.js @@ -24,7 +24,8 @@ function register(editor, url) { }, onSetup(api) { editor.on('NodeChange', event => { - const inList = event.parents.find(el => el.nodeName === 'LI' && el.classList.contains('task-list-item')) !== undefined; + const parentListEl = event.parents.find(el => el.nodeName === 'LI'); + const inList = parentListEl && parentListEl.classList.contains('task-list-item'); api.setActive(inList); }); } @@ -35,12 +36,22 @@ function register(editor, url) { const existingBullListButton = editor.ui.registry.getAll().buttons.bullist; existingBullListButton.onSetup = function(api) { editor.on('NodeChange', event => { - const notInTaskList = event.parents.find(el => el.nodeName === 'LI' && el.classList.contains('task-list-item')) === undefined; - const inList = event.parents.find(el => el.nodeName === 'UL') !== undefined; - api.setActive(inList && notInTaskList); + const parentList = event.parents.find(el => el.nodeName === 'LI'); + const inTaskList = parentList && parentList.classList.contains('task-list-item'); + const inUlList = parentList && parentList.parentNode.nodeName === 'UL'; + api.setActive(inUlList && !inTaskList); }); }; existingBullListButton.onAction = function() { + // Cheeky hack to prevent list toggle action treating tasklists as normal + // unordered lists which would unwrap the list on toggle from tasklist to bullet list. + // Instead we quickly jump through an ordered list first if we're within a tasklist. + if (elementWithinTaskList(editor.selection.getNode())) { + editor.execCommand('InsertOrderedList', null, { + 'list-item-attributes': {class: null} + }); + } + editor.execCommand('InsertUnorderedList', null, { 'list-item-attributes': {class: null} }); @@ -80,6 +91,15 @@ function register(editor, url) { }); } +/** + * @param {Element} element + * @return {boolean} + */ +function elementWithinTaskList(element) { + const listEl = element.closest('li'); + return listEl && listEl.parentNode.nodeName === 'UL' && listEl.classList.contains('task-list-item'); +} + /** * @param {MouseEvent} event * @param {Element} clickedEl @@ -126,6 +146,7 @@ function parseTaskListNode(node) { * @param {AstNode} node */ function serializeTaskListNode(node) { + // Get checked status and clean it from list node const isChecked = node.attr('checked') === 'checked'; node.attr('checked', null); @@ -134,6 +155,7 @@ function serializeTaskListNode(node) { inputAttrs.checked = 'checked'; } + // Create & insert checkbox input element const checkbox = new tinymce.html.Node.create('input', inputAttrs); checkbox.shortEnded = true; node.firstChild ? node.insert(checkbox, node.firstChild, true) : node.append(checkbox); diff --git a/resources/js/wysiwyg/toolbars.js b/resources/js/wysiwyg/toolbars.js index 4f8897f84..740220d84 100644 --- a/resources/js/wysiwyg/toolbars.js +++ b/resources/js/wysiwyg/toolbars.js @@ -10,7 +10,7 @@ export function getPrimaryToolbar(options) { 'styleselect', 'bold italic underline forecolor backcolor formatoverflow', 'alignleft aligncenter alignright alignjustify', - 'bullist numlist tasklist listoverflow', + 'bullist numlist listoverflow', textDirPlugins, 'link table imagemanager-insert insertoverflow', 'code about fullscreen' @@ -31,7 +31,7 @@ function registerPrimaryToolbarGroups(editor) { editor.ui.registry.addGroupToolbarButton('listoverflow', { icon: 'more-drawer', tooltip: 'More', - items: 'outdent indent' + items: 'tasklist outdent indent' }); editor.ui.registry.addGroupToolbarButton('insertoverflow', { icon: 'more-drawer',