Schema Definition
Schema definition for the Accordion node type:
{
accordion: {
content: 'block+',
group: 'block',
attrs: {
open: { default: false }
}
}
}Model Representation
Example model representation:
{
type: 'accordion',
attrs: { open: false },
children: [
{
type: 'heading',
level: 3,
children: [{ type: 'text', text: 'Accordion Title' }]
},
{
type: 'paragraph',
children: [{ type: 'text', text: 'Accordion content' }]
}
]
}HTML Serialization
Converting model to HTML:
function serializeAccordion(node) {
return '<div data-type="accordion" data-open="' + node.attrs.open + '">' +
serializeChildren(node.children) + '</div>';
}HTML Deserialization
Parsing HTML to model:
function parseAccordion(domNode) {
return {
type: 'accordion',
attrs: { open: domNode.getAttribute('data-open') === 'true' },
children: Array.from(domNode.childNodes)
.map(node => parseNode(node))
.filter(Boolean)
};
}View Integration
View Integration Notes: Pay special attention to contenteditable behavior, selection handling, and event management when implementing this node type in your view layer.
View integration code:
// Rendering accordion
const accordion = document.createElement('div');
accordion.setAttribute('data-type', 'accordion');
accordion.setAttribute('data-open', node.attrs.open);
accordion.contentEditable = 'true';
node.children.forEach(child => {
accordion.appendChild(renderNode(child));
});
// Toggle accordion
function toggleAccordion(accordion) {
const isOpen = accordion.getAttribute('data-open') === 'true';
accordion.setAttribute('data-open', !isOpen);
updateAccordionContent(accordion, !isOpen);
}Common Issues
Common Pitfalls: These are issues frequently encountered when implementing this node type. Review carefully before implementation.
Common issues and solutions:
// Issue: Accordion state management
// Solution: Sync state between model and view
function syncAccordionState(accordion, model) {
accordion.setAttribute('data-open', model.attrs.open);
}
// Issue: Nested accordions
// Solution: Handle nested accordion behavior
function handleNestedAccordion(parent, child) {
// Prevent parent from closing when child toggles
}Implementation
Complete implementation example:
class AccordionNode {
constructor(attrs, children) {
this.type = 'accordion';
this.attrs = { open: attrs?.open || false };
this.children = children || [];
}
toDOM() {
const accordion = document.createElement('div');
accordion.setAttribute('data-type', 'accordion');
accordion.setAttribute('data-open', this.attrs.open);
this.children.forEach(child => {
accordion.appendChild(child.toDOM());
});
return accordion;
}
static fromDOM(domNode) {
return new AccordionNode(
{ open: domNode.getAttribute('data-open') === 'true' },
Array.from(domNode.childNodes)
.map(node => parseNode(node))
.filter(Boolean)
);
}
}