📖 Basic Plugin Development
The Basic Structure
Every plugin exports an object with a mount function:
export default {
name: 'plugin-name', // Plugin identifier
displayName: 'My Plugin', // Optional: friendly name shown in UI
version: '1.0.0', // Version number
mount: function(element, options) {
// Your code here
return {};
}
};
The mount Function
This is the heart of your plugin. It runs for every element that uses your plugin.
mount: function(element, options) {
// element = the HTML element (<div>, <button>, etc.)
// options = settings from data-cb-* attributes or settings UI
// Do your magic here...
// Always return an object (or null on error)
return { /* anything you want to track */ };
}
Key Points:
- Gets called once per element
- Receives the element and its options
- Must return an object (can be empty
{}ornullon error) - Can be async if needed for complex initialization
Getting Options from HTML
Options come from data-cb-* attributes:
HTML:
<div data-cb-type="tooltip"
data-cb-text="Hello"
data-cb-position="top">
</div>
JavaScript:
mount: function(element, options) {
var text = options.text; // "Hello"
var position = options.position; // "top"
}
Rules:
- Attributes must start with
data-cb- - Use lowercase with hyphens:
data-cb-my-option - Access in code with camelCase:
options.myOption
More Examples
Example 1: Simple Tooltip
Shows a tooltip when hovering over an element.
javascript
export default {
name: 'tooltip',
version: '1.0.0',
mount: function(element, options) {
var tooltipText = options.text || 'Tooltip';
var tooltip = document.createElement('div');
// Style the tooltip
tooltip.textContent = tooltipText;
tooltip.style.cssText = 'position:fixed; background:#333; color:#fff; ' +
'padding:5px 10px; border-radius:4px; ' +
'font-size:12px; display:none; z-index:9999;';
document.body.appendChild(tooltip);
// Show on hover
element.addEventListener('mouseenter', function(e) {
tooltip.style.display = 'block';
tooltip.style.left = e.clientX + 10 + 'px';
tooltip.style.top = e.clientY + 10 + 'px';
});
// Hide when mouse leaves
element.addEventListener('mouseleave', function() {
tooltip.style.display = 'none';
});
return { tooltip: tooltip };
}
};
Usage:
html
<span data-cb-type="tooltip" data-cb-text="Helpful information">
Hover me
</span>
Example 2: Toggle Visibility
Shows/hides another element when clicked.
javascript
export default {
name: 'toggle',
version: '1.0.0',
mount: function(element, options) {
var targetId = options.target;
var target = document.getElementById(targetId);
if (!target) {
console.error('Target element not found:', targetId);
return null;
}
element.addEventListener('click', function() {
if (target.style.display === 'none') {
target.style.display = 'block';
} else {
target.style.display = 'none';
}
});
return { target: target };
}
};
Usage:
html
<button data-cb-type="toggle" data-cb-target="myContent">
Toggle Content
</button>
<div id="myContent">
This content can be shown/hidden
</div>
Cleanup with unmount
If your plugin needs cleanup (remove event listeners, timers, etc.), add an unmount function:
export default {
name: 'my-plugin',
version: '1.0.0',
mount: function(element, options) {
var timer = setInterval(function() {
console.log('Running...');
}, 1000);
return {
timer: timer,
stop: function() {
clearInterval(timer);
}
};
},
unmount: function(element, instance) {
if (instance && instance.stop) {
instance.stop();
}
}
};
Async Mount for Complex Plugins
For plugins that need complex initialization:
export default {
name: 'complex-plugin',
version: '1.0.0',
async mount(element, options) {
try {
await someAsyncOperation();
const instance = createComponent(element, options);
return instance;
} catch (error) {
console.error('Plugin mount error:', error);
return null;
}
}
};
Class-Based Pattern
For sophisticated plugins, use a class-based approach:
class MyComponent {
constructor(element, options) {
this.element = element;
this.options = options;
this.init();
}
init() {
// Setup your component
}
destroy() {
// Cleanup
}
}
export default {
name: 'my-plugin',
version: '1.0.0',
async mount(element, options) {
try {
const instance = new MyComponent(element, options);
return instance;
} catch (error) {
console.error('Mount error:', error);
return null;
}
},
unmount(element, instance) {
if (instance && typeof instance.destroy === 'function') {
instance.destroy();
}
}
};