suneditor
Version:
Vanilla JavaScript based WYSIWYG web editor
145 lines (125 loc) • 3.77 kB
JavaScript
import { PluginDropdown } from '../../interfaces';
import { dom } from '../../helper';
/**
* @typedef {Object} ParagraphStylePluginOptions
* @property {Array<string|{name: string, class: string, _class: string}>} [items] - Paragraph item list
* ```js
* // use default paragraph styles
* ['spaced', 'bordered', 'neon']
* // custom paragraph styles
* [
* { name: 'spaced', class: '__se__p-spaced', _class: '' },
* { name: 'bordered', class: '__se__p-bordered', _class: '' },
* { name: 'neon', class: '__se__p-neon', _class: '' }
* ]
* ```
*/
/**
* @class
* @description A plugin to style lines using classes.
*/
class ParagraphStyle extends PluginDropdown {
static key = 'paragraphStyle';
static className = '';
/**
* @constructor
* @param {SunEditor.Kernel} kernel - The Kernel instance
* @param {ParagraphStylePluginOptions} pluginOptions - Plugin options
*/
constructor(kernel, pluginOptions) {
// plugin bisic properties
super(kernel);
this.title = this.$.lang.paragraphStyle;
this.icon = 'paragraph_style';
// create HTML
const menu = CreateHTML(this.$, pluginOptions.items);
// members
this.classList = menu.querySelectorAll('li button');
// init
this.$.menu.initDropdownTarget(ParagraphStyle, menu);
}
/**
* @override
* @type {PluginDropdown['on']}
*/
on() {
const paragraphList = this.classList;
const currentFormat = this.$.format.getLine(this.$.selection.getNode());
for (let i = 0, len = paragraphList.length; i < len; i++) {
if (dom.utils.hasClass(currentFormat, paragraphList[i].getAttribute('data-command'))) {
dom.utils.addClass(paragraphList[i], 'active');
} else {
dom.utils.removeClass(paragraphList[i], 'active');
}
}
}
/**
* @override
* @type {PluginDropdown['action']}
*/
action(target) {
const value = target.getAttribute('data-command');
let selectedFormsts = this.$.format.getLines();
if (selectedFormsts.length === 0) {
this.$.selection.getRangeAndAddLine(this.$.selection.getRange(), null);
selectedFormsts = this.$.format.getLines();
if (selectedFormsts.length === 0) return;
}
// change format class
for (let i = 0, len = selectedFormsts.length; i < len; i++) {
dom.utils.toggleClass(selectedFormsts[i], value);
}
this.$.menu.dropdownOff();
this.$.history.push(false);
}
}
/**
* @param {SunEditor.Deps} $ - Kernel dependencies
* @param {Array<string|{name: string, class: string, _class?: string}>} [items] - Paragraph style items
* @returns {HTMLElement}
*/
function CreateHTML({ lang }, items) {
const defaultList = {
spaced: {
name: lang.menu_spaced,
class: '__se__p-spaced',
_class: '',
},
bordered: {
name: lang.menu_bordered,
class: '__se__p-bordered',
_class: '',
},
neon: {
name: lang.menu_neon,
class: '__se__p-neon',
_class: '',
},
};
const paragraphStyles = !items || items.length === 0 ? ['spaced', 'bordered', 'neon'] : items;
let list = /*html*/ `
<div class="se-list-inner">
<ul class="se-list-basic">`;
for (let i = 0, len = paragraphStyles.length, p, name, attrs, _class; i < len; i++) {
p = paragraphStyles[i];
if (typeof p === 'string') {
const cssText = defaultList[p.toLowerCase()];
if (!cssText) continue;
p = cssText;
}
name = p.name;
attrs = p.class ? ` class="${p.class}"` : '';
_class = p._class;
list += /*html*/ `
<li>
<button type="button" class="se-btn se-btn-list${_class ? ' ' + _class : ''}" data-command="${p.class}" title="${name}" aria-label="${name}">
<div${attrs}>${name}</div>
</button>
</li>`;
}
list += /*html*/ `
</ul>
</div>`;
return dom.utils.createElement('DIV', { class: 'se-dropdown se-list-layer se-list-format' }, list);
}
export default ParagraphStyle;