178 lines
6.7 KiB
JavaScript
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\>| )*$/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;
|
|
}); |