Skip to content

Commit

Permalink
feat: implement missing event handling for seamless authoring experie…
Browse files Browse the repository at this point in the history
…nce (#3)

* feat: support instant reloading of default content
* fix: reload for sections
* fix: merge richtexts
* fix: listen for content-update
* fix: do not listen for content-update
* feat: handle content-update the same way as patch
* feat: handle section and main updates
* feat: handle move
* fix: block reload with auto blocks
  • Loading branch information
buuhuu authored Feb 21, 2024
1 parent df80168 commit bfff71c
Showing 1 changed file with 89 additions and 26 deletions.
115 changes: 89 additions & 26 deletions scripts/editor-support.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,105 @@
import {
decorateBlock,
decorateBlocks,
decorateButtons,
decorateIcons,
decorateSections,
loadBlock,
loadBlocks,
} from './aem.js';
// eslint-disable-next-line import/no-unresolved
import { decorateRichtext } from './editor-support-rte.js';
import { decorateMain } from './scripts.js';

const connectionPrefix = 'urn:aemconnection:';

async function handleEditorUpdate(event) {
async function applyChanges(event) {
// redecorate default content and blocks on patches (in the properties rail)
const { detail } = event;

const resource = detail?.request?.target?.resource;
if (!resource) return;
const resource = detail?.request?.target?.resource // update, patch components
|| detail?.request?.target?.container?.resource // update, patch, add to sections
|| detail?.request?.to?.container?.resource; // move in sections
if (!resource) return false;
const updates = detail?.response?.updates;
if (!updates.length) return false;
const { content } = updates[0];
if (!content) return false;

const parsedUpdate = new DOMParser().parseFromString(content, 'text/html');
const element = document.querySelector(`[data-aue-resource="${resource}"]`);
const block = element?.parentElement?.closest('.block') || element?.closest('.block');
const blockResource = block?.getAttribute('data-aue-resource');
if (!block || !blockResource?.startsWith(connectionPrefix)) return;

const updates = detail?.response?.updates;
if (updates.length > 0) {
const { content } = updates[0];
const newBlockDocument = new DOMParser().parseFromString(content, 'text/html');
const newBlock = newBlockDocument?.querySelector(`[data-aue-resource="${blockResource}"]`);
if (newBlock) {
newBlock.style.display = 'none';
block.insertAdjacentElement('afterend', newBlock);
// decorate buttons and icons
decorateButtons(newBlock);
decorateIcons(newBlock);
// decorate and load the block
decorateBlock(newBlock);
await loadBlock(newBlock);
// remove the old block and show the new one
block.remove();
newBlock.style.display = null;
if (element) {
if (element.matches('main')) {
const newMain = parsedUpdate.querySelector(`[data-aue-resource="${resource}"]`);
newMain.style.display = 'none';
element.insertAdjacentElement('afterend', newMain);
decorateMain(newMain);
decorateRichtext(newMain);
await loadBlocks(newMain);
element.remove();
newMain.style.display = null;
// eslint-disable-next-line no-use-before-define
attachEventListners(newMain);
return true;
}

const block = element.parentElement?.closest('.block[data-aue-resource]') || element?.closest('.block[data-aue-resource]');
if (block) {
const blockResource = block.getAttribute('data-aue-resource');
const newBlock = parsedUpdate.querySelector(`[data-aue-resource="${blockResource}"]`);
if (newBlock) {
newBlock.style.display = 'none';
block.insertAdjacentElement('afterend', newBlock);
decorateButtons(newBlock);
decorateIcons(newBlock);
decorateBlock(newBlock);
await loadBlock(newBlock);
block.remove();
newBlock.style.display = null;
return true;
}
} else {
// sections and default content, may be multiple in the case of richtext
const newElements = parsedUpdate.querySelectorAll(`[data-aue-resource="${resource}"],[data-richtext-resource="${resource}"]`);
if (newElements.length) {
const { parentElement } = element;
if (element.matches('.section')) {
const [newSection] = newElements;
newSection.style.display = 'none';
element.insertAdjacentElement('afterend', newSection);
decorateButtons(newSection);
decorateIcons(newSection);
decorateRichtext(newSection);
decorateSections(parentElement);
decorateBlocks(parentElement);
await loadBlocks(newSection);
element.remove();
newSection.style.display = null;
} else {
element.replaceWith(...newElements);
decorateButtons(parentElement);
decorateIcons(parentElement);
decorateRichtext(parentElement);
}
return true;
}
}
}

return false;
}

function attachEventListners(main) {
[
'aue:content-patch',
'aue:content-update',
'aue:content-add',
'aue:content-move',
'aue:content-remove',
].forEach((eventType) => main?.addEventListener(eventType, async (event) => {
event.stopPropagation();
const applied = await applyChanges(event);
if (!applied) window.location.reload();
}));
}

document.querySelector('main')?.addEventListener('aue:content-patch', handleEditorUpdate);
attachEventListners(document.querySelector('main'));

0 comments on commit bfff71c

Please sign in to comment.