2023-04-28 12:22:26 +08:00

178 lines
6.7 KiB
JavaScript

!function (factory) {
if (typeof define === 'function' && define.amd) {
define([], function () {
return factory(window.jQuery);
});
}
}(function ($) {
'use strict';
function Editor(element, options) {
this.selectedRange = null;
this.container = $(element);
var editor = $('<div class="editor-content"></div>');
this.container.find('.editor-content').remove();
this.container.append(editor);
this.editor = editor;
var defaults = {
toolbarSelector: '.editor-toolbar',
commandRole: 'edit',
activeToolbarClass: 'selected',
selectionColor: 'darkgray'
};
var opts = $.extend(true, {}, defaults, options);
var toolbarBtnSelector = 'a[data-' + opts.commandRole + '],button[data-' + opts.commandRole + '],input[type=button][data-' + opts.commandRole + ']';
this.bindHotkeys(editor, opts, toolbarBtnSelector);
this.bindToolbar(editor, this.container.find(opts.toolbarSelector), opts, toolbarBtnSelector);
editor.attr('contenteditable', true).on('mouseup keyup mouseout', function () {
this.saveSelection();
this.updateToolbar(toolbarBtnSelector, opts);
}.bind(this));
$(window).bind('touchend', function (e) {
if (!this.getCurrentRange) {
return;
}
var inside = (editor.is(e.target) || editor.has(e.target).length > 0),
currentRange = this.getCurrentRange(),
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
if (!clear || inside) {
this.saveSelection();
this.updateToolbar(toolbarBtnSelector, opts);
}
});
}
Editor.prototype.cleanHtml = function () {
var html = this.editor.html();
return html && html.replace(/(\<br\>|\s|\<div\>\<br\>\<\/div\>|&nbsp;)*$/g, '');
};
Editor.prototype.updateToolbar = function (selector, options) {
if (options.activeToolbarClass) {
this.container.find(options.toolbarSelector).find(selector).each(function () {
var This = $(this);
var commandArray = This.data(options.commandRole).split(' ');
var command = commandArray[0];
if (commandArray.length > 1 && document.queryCommandEnabled(command) && document.queryCommandValue(command) === commandArray[1]) {
This.addClass(options.activeToolbarClass);
} else if (commandArray.length === [1] && document.queryCommandEnabled(command) && document.queryCommandState(command)) {
This.addClass(options.activeToolbarClass);
} else {
This.removeClass(options.activeToolbarClass);
}
});
}
};
Editor.prototype.execCommand = function (commandWithArgs, valueArg, editor, options, selector) {
var commandArray = commandWithArgs.split(' '),
command = commandArray.shift(),
args = commandArray.join(' ') + (valueArg || '');
var parts = commandWithArgs.split('-');
if (parts.length === 1) {
document.execCommand(command, false, args);
} else if (parts.length === 2) {
document.execCommand(parts[0], false, parts[1]);
}
editor.trigger('change');
this.updateToolbar(selector, options);
};
Editor.prototype.bindHotkeys = function (editor, options, selector) {
var This = this;
editor.on('keydown', function (e) {
if (e.key === 'Tab') {
var command = e.shiftKey ? 'outdent' : 'indent';
e.preventDefault();
e.stopPropagation();
This.execCommand(command, null, editor, options, selector);
}
}).on('keyup', function () {
editor.trigger('change');
});
};
Editor.prototype.getCurrentRange = function () {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
}
} else if (document.selection) {
range = document.selection.createRange();
}
return range;
};
Editor.prototype.saveSelection = function () {
this.selectedRange = this.getCurrentRange();
}
Editor.prototype.restoreSelection = function () {
var selection;
if (window.getSelection || document.createRange) {
selection = window.getSelection();
if (this.selectedRange) {
try {
selection.removeAllRanges();
} catch {
document.body.createTextRange().select();
document.selection.empty();
}
selection.addRange(this.selectedRange);
}
} else if (document.selection && this.selectedRange) {
this.selectedRange.select();
}
};
Editor.prototype.markSelection = function (color) {
this.restoreSelection();
if (document.queryCommandSupported('hiliteColor')) {
document.execCommand('hiliteColor', false, color || 'transparent');
}
this.saveSelection();
};
Editor.prototype.bindToolbar = function (editor, toolbar, options, selector) {
var This = this;
toolbar.find(selector).on('click', function () {
var command = $(this).data(options.commandRole);
if (command === 'createlink') {
var link = prompt('Write the URL here', 'https:\/\/');
This.restoreSelection();
editor.focus();
if (link == null || link === '' || link === 'https:\/\/') {
This.saveSelection();
return;
}
This.execCommand(command, link, editor, options, selector);
} else {
This.restoreSelection();
editor.focus();
This.execCommand(command, null, editor, options, selector);
This.saveSelection();
}
});
toolbar.find('select').on('change', function () {
var command = $(this).data(options.commandRole);
var value = $(this).val();
if (value == null || value === '') {
editor.focus();
return;
}
This.execCommand(command + '-' + value, null, editor, options, selector);
editor.focus();
this.selectedIndex = 0;
});
};
return Editor;
});