hdjs
Version:
hdjs framework
1,511 lines (1,420 loc) • 181 kB
JavaScript
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module unless amdModuleId is set
define('simditor', ["jquery","simple-module","simple-hotkeys","simple-uploader"], function ($, SimpleModule, simpleHotkeys, simpleUploader) {
return (root['Simditor'] = factory($, SimpleModule, simpleHotkeys, simpleUploader));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require("jquery"),require("simple-module"),require("simple-hotkeys"),require("simple-uploader"));
} else {
root['Simditor'] = factory(jQuery,SimpleModule,simple.hotkeys,simple.uploader);
}
}(this, function ($, SimpleModule, simpleHotkeys, simpleUploader) {
var AlignmentButton, BlockquoteButton, BoldButton, Button, Clipboard, CodeButton, CodePopover, ColorButton, FontScaleButton, Formatter, HrButton, ImageButton, ImagePopover, IndentButton, Indentation, InputManager, ItalicButton, Keystroke, LinkButton, LinkPopover, ListButton, OrderListButton, OutdentButton, Popover, Selection, Simditor, StrikethroughButton, TableButton, TitleButton, Toolbar, UnderlineButton, UndoManager, UnorderListButton, Util,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
slice = [].slice;
Selection = (function(superClass) {
extend(Selection, superClass);
function Selection() {
return Selection.__super__.constructor.apply(this, arguments);
}
Selection.pluginName = 'Selection';
Selection.prototype._range = null;
Selection.prototype._startNodes = null;
Selection.prototype._endNodes = null;
Selection.prototype._containerNode = null;
Selection.prototype._nodes = null;
Selection.prototype._blockNodes = null;
Selection.prototype._rootNodes = null;
Selection.prototype._init = function() {
this.editor = this._module;
this._selection = document.getSelection();
this.editor.on('selectionchanged', (function(_this) {
return function(e) {
_this.reset();
return _this._range = _this._selection.getRangeAt(0);
};
})(this));
this.editor.on('blur', (function(_this) {
return function(e) {
return _this.reset();
};
})(this));
return this.editor.on('focus', (function(_this) {
return function(e) {
_this.reset();
return _this._range = _this._selection.getRangeAt(0);
};
})(this));
};
Selection.prototype.reset = function() {
this._range = null;
this._startNodes = null;
this._endNodes = null;
this._containerNode = null;
this._nodes = null;
this._blockNodes = null;
return this._rootNodes = null;
};
Selection.prototype.clear = function() {
var e;
try {
this._selection.removeAllRanges();
} catch (_error) {
e = _error;
}
return this.reset();
};
Selection.prototype.range = function(range) {
var ffOrIE;
if (range) {
this.clear();
this._selection.addRange(range);
this._range = range;
ffOrIE = this.editor.util.browser.firefox || this.editor.util.browser.msie;
if (!this.editor.inputManager.focused && ffOrIE) {
this.editor.body.focus();
}
} else if (!this._range && this.editor.inputManager.focused && this._selection.rangeCount) {
this._range = this._selection.getRangeAt(0);
}
return this._range;
};
Selection.prototype.startNodes = function() {
if (this._range) {
this._startNodes || (this._startNodes = (function(_this) {
return function() {
var startNodes;
startNodes = $(_this._range.startContainer).parentsUntil(_this.editor.body).get();
startNodes.unshift(_this._range.startContainer);
return $(startNodes);
};
})(this)());
}
return this._startNodes;
};
Selection.prototype.endNodes = function() {
var endNodes;
if (this._range) {
this._endNodes || (this._endNodes = this._range.collapsed ? this.startNodes() : (endNodes = $(this._range.endContainer).parentsUntil(this.editor.body).get(), endNodes.unshift(this._range.endContainer), $(endNodes)));
}
return this._endNodes;
};
Selection.prototype.containerNode = function() {
if (this._range) {
this._containerNode || (this._containerNode = $(this._range.commonAncestorContainer));
}
return this._containerNode;
};
Selection.prototype.nodes = function() {
if (this._range) {
this._nodes || (this._nodes = (function(_this) {
return function() {
var nodes;
nodes = [];
if (_this.startNodes().first().is(_this.endNodes().first())) {
nodes = _this.startNodes().get();
} else {
_this.startNodes().each(function(i, node) {
var $endNode, $node, $nodes, endIndex, index, sharedIndex, startIndex;
$node = $(node);
if (_this.endNodes().index($node) > -1) {
return nodes.push(node);
} else if ($node.parent().is(_this.editor.body) || (sharedIndex = _this.endNodes().index($node.parent())) > -1) {
if (sharedIndex && sharedIndex > -1) {
$endNode = _this.endNodes().eq(sharedIndex - 1);
} else {
$endNode = _this.endNodes().last();
}
$nodes = $node.parent().contents();
startIndex = $nodes.index($node);
endIndex = $nodes.index($endNode);
return $.merge(nodes, $nodes.slice(startIndex, endIndex).get());
} else {
$nodes = $node.parent().contents();
index = $nodes.index($node);
return $.merge(nodes, $nodes.slice(index).get());
}
});
_this.endNodes().each(function(i, node) {
var $node, $nodes, index;
$node = $(node);
if ($node.parent().is(_this.editor.body) || _this.startNodes().index($node.parent()) > -1) {
nodes.push(node);
return false;
} else {
$nodes = $node.parent().contents();
index = $nodes.index($node);
return $.merge(nodes, $nodes.slice(0, index + 1));
}
});
}
return $($.unique(nodes));
};
})(this)());
}
return this._nodes;
};
Selection.prototype.blockNodes = function() {
if (!this._range) {
return;
}
this._blockNodes || (this._blockNodes = (function(_this) {
return function() {
return _this.nodes().filter(function(i, node) {
return _this.editor.util.isBlockNode(node);
});
};
})(this)());
return this._blockNodes;
};
Selection.prototype.rootNodes = function() {
if (!this._range) {
return;
}
this._rootNodes || (this._rootNodes = (function(_this) {
return function() {
return _this.nodes().filter(function(i, node) {
var $parent;
$parent = $(node).parent();
return $parent.is(_this.editor.body) || $parent.is('blockquote');
});
};
})(this)());
return this._rootNodes;
};
Selection.prototype.rangeAtEndOf = function(node, range) {
var afterLastNode, beforeLastNode, endNode, endNodeLength, lastNodeIsBr, result;
if (range == null) {
range = this.range();
}
if (!(range && range.collapsed)) {
return;
}
node = $(node)[0];
endNode = range.endContainer;
endNodeLength = this.editor.util.getNodeLength(endNode);
beforeLastNode = range.endOffset === endNodeLength - 1;
lastNodeIsBr = $(endNode).contents().last().is('br');
afterLastNode = range.endOffset === endNodeLength;
if (!((beforeLastNode && lastNodeIsBr) || afterLastNode)) {
return false;
}
if (node === endNode) {
return true;
} else if (!$.contains(node, endNode)) {
return false;
}
result = true;
$(endNode).parentsUntil(node).addBack().each(function(i, n) {
var $lastChild, beforeLastbr, isLastNode, nodes;
nodes = $(n).parent().contents().filter(function() {
return !(this !== n && this.nodeType === 3 && !this.nodeValue);
});
$lastChild = nodes.last();
isLastNode = $lastChild.get(0) === n;
beforeLastbr = $lastChild.is('br') && $lastChild.prev().get(0) === n;
if (!(isLastNode || beforeLastbr)) {
result = false;
return false;
}
});
return result;
};
Selection.prototype.rangeAtStartOf = function(node, range) {
var result, startNode;
if (range == null) {
range = this.range();
}
if (!(range && range.collapsed)) {
return;
}
node = $(node)[0];
startNode = range.startContainer;
if (range.startOffset !== 0) {
return false;
}
if (node === startNode) {
return true;
} else if (!$.contains(node, startNode)) {
return false;
}
result = true;
$(startNode).parentsUntil(node).addBack().each(function(i, n) {
var nodes;
nodes = $(n).parent().contents().filter(function() {
return !(this !== n && this.nodeType === 3 && !this.nodeValue);
});
if (nodes.first().get(0) !== n) {
return result = false;
}
});
return result;
};
Selection.prototype.insertNode = function(node, range) {
if (range == null) {
range = this.range();
}
if (!range) {
return;
}
node = $(node)[0];
range.insertNode(node);
return this.setRangeAfter(node, range);
};
Selection.prototype.setRangeAfter = function(node, range) {
if (range == null) {
range = this.range();
}
if (range == null) {
return;
}
node = $(node)[0];
range.setEndAfter(node);
range.collapse(false);
return this.range(range);
};
Selection.prototype.setRangeBefore = function(node, range) {
if (range == null) {
range = this.range();
}
if (range == null) {
return;
}
node = $(node)[0];
range.setEndBefore(node);
range.collapse(false);
return this.range(range);
};
Selection.prototype.setRangeAtStartOf = function(node, range) {
if (range == null) {
range = this.range();
}
node = $(node).get(0);
range.setEnd(node, 0);
range.collapse(false);
return this.range(range);
};
Selection.prototype.setRangeAtEndOf = function(node, range) {
var $lastNode, $node, contents, lastChild, lastChildLength, lastText, nodeLength;
if (range == null) {
range = this.range();
}
$node = $(node);
node = $node[0];
if (!node) {
return;
}
if ($node.is('pre')) {
contents = $node.contents();
if (contents.length > 0) {
lastChild = contents.last();
lastText = lastChild.text();
lastChildLength = this.editor.util.getNodeLength(lastChild[0]);
if (lastText.charAt(lastText.length - 1) === '\n') {
range.setEnd(lastChild[0], lastChildLength - 1);
} else {
range.setEnd(lastChild[0], lastChildLength);
}
} else {
range.setEnd(node, 0);
}
} else {
nodeLength = this.editor.util.getNodeLength(node);
if (node.nodeType !== 3 && nodeLength > 0) {
$lastNode = $(node).contents().last();
if ($lastNode.is('br')) {
nodeLength -= 1;
} else if ($lastNode[0].nodeType !== 3 && this.editor.util.isEmptyNode($lastNode)) {
$lastNode.append(this.editor.util.phBr);
node = $lastNode[0];
nodeLength = 0;
}
}
range.setEnd(node, nodeLength);
}
range.collapse(false);
return this.range(range);
};
Selection.prototype.deleteRangeContents = function(range) {
var atEndOfBody, atStartOfBody, endRange, startRange;
if (range == null) {
range = this.range();
}
startRange = range.cloneRange();
endRange = range.cloneRange();
startRange.collapse(true);
endRange.collapse(false);
atStartOfBody = this.rangeAtStartOf(this.editor.body, startRange);
atEndOfBody = this.rangeAtEndOf(this.editor.body, endRange);
if (!range.collapsed && atStartOfBody && atEndOfBody) {
this.editor.body.empty();
range.setStart(this.editor.body[0], 0);
range.collapse(true);
this.range(range);
} else {
range.deleteContents();
}
return range;
};
Selection.prototype.breakBlockEl = function(el, range) {
var $el;
if (range == null) {
range = this.range();
}
$el = $(el);
if (!range.collapsed) {
return $el;
}
range.setStartBefore($el.get(0));
if (range.collapsed) {
return $el;
}
return $el.before(range.extractContents());
};
Selection.prototype.save = function(range) {
var endCaret, endRange, startCaret;
if (range == null) {
range = this.range();
}
if (this._selectionSaved) {
return;
}
endRange = range.cloneRange();
endRange.collapse(false);
startCaret = $('<span/>').addClass('simditor-caret-start');
endCaret = $('<span/>').addClass('simditor-caret-end');
endRange.insertNode(endCaret[0]);
range.insertNode(startCaret[0]);
this.clear();
return this._selectionSaved = true;
};
Selection.prototype.restore = function() {
var endCaret, endContainer, endOffset, range, startCaret, startContainer, startOffset;
if (!this._selectionSaved) {
return false;
}
startCaret = this.editor.body.find('.simditor-caret-start');
endCaret = this.editor.body.find('.simditor-caret-end');
if (startCaret.length && endCaret.length) {
startContainer = startCaret.parent();
startOffset = startContainer.contents().index(startCaret);
endContainer = endCaret.parent();
endOffset = endContainer.contents().index(endCaret);
if (startContainer[0] === endContainer[0]) {
endOffset -= 1;
}
range = document.createRange();
range.setStart(startContainer.get(0), startOffset);
range.setEnd(endContainer.get(0), endOffset);
startCaret.remove();
endCaret.remove();
this.range(range);
} else {
startCaret.remove();
endCaret.remove();
}
this._selectionSaved = false;
return range;
};
return Selection;
})(SimpleModule);
Formatter = (function(superClass) {
extend(Formatter, superClass);
function Formatter() {
return Formatter.__super__.constructor.apply(this, arguments);
}
Formatter.pluginName = 'Formatter';
Formatter.prototype.opts = {
allowedTags: [],
allowedAttributes: {},
allowedStyles: {}
};
Formatter.prototype._init = function() {
this.editor = this._module;
this._allowedTags = $.merge(['br', 'span', 'a', 'img', 'b', 'strong', 'i', 'strike', 'u', 'font', 'p', 'ul', 'ol', 'li', 'blockquote', 'pre', 'code', 'h1', 'h2', 'h3', 'h4', 'hr'], this.opts.allowedTags);
this._allowedAttributes = $.extend({
img: ['src', 'alt', 'width', 'height', 'data-non-image'],
a: ['href', 'target'],
font: ['color'],
code: ['class']
}, this.opts.allowedAttributes);
this._allowedStyles = $.extend({
span: ['color', 'font-size'],
b: ['color', 'font-size'],
i: ['color', 'font-size'],
strong: ['color', 'font-size'],
strike: ['color', 'font-size'],
u: ['color', 'font-size'],
p: ['margin-left', 'text-align'],
h1: ['margin-left', 'text-align'],
h2: ['margin-left', 'text-align'],
h3: ['margin-left', 'text-align'],
h4: ['margin-left', 'text-align']
}, this.opts.allowedStyles);
return this.editor.body.on('click', 'a', function(e) {
return false;
});
};
Formatter.prototype.decorate = function($el) {
if ($el == null) {
$el = this.editor.body;
}
this.editor.trigger('decorate', [$el]);
return $el;
};
Formatter.prototype.undecorate = function($el) {
if ($el == null) {
$el = this.editor.body.clone();
}
this.editor.trigger('undecorate', [$el]);
return $el;
};
Formatter.prototype.autolink = function($el) {
var $link, $node, findLinkNode, k, lastIndex, len, linkNodes, match, re, replaceEls, subStr, text, uri;
if ($el == null) {
$el = this.editor.body;
}
linkNodes = [];
findLinkNode = function($parentNode) {
return $parentNode.contents().each(function(i, node) {
var $node, text;
$node = $(node);
if ($node.is('a') || $node.closest('a, pre', $el).length) {
return;
}
if (!$node.is('iframe') && $node.contents().length) {
return findLinkNode($node);
} else if ((text = $node.text()) && /https?:\/\/|www\./ig.test(text)) {
return linkNodes.push($node);
}
});
};
findLinkNode($el);
re = /(https?:\/\/|www\.)[\w\-\.\?&=\/#%:,@\!\+]+/ig;
for (k = 0, len = linkNodes.length; k < len; k++) {
$node = linkNodes[k];
text = $node.text();
replaceEls = [];
match = null;
lastIndex = 0;
while ((match = re.exec(text)) !== null) {
subStr = text.substring(lastIndex, match.index);
replaceEls.push(document.createTextNode(subStr));
lastIndex = re.lastIndex;
uri = /^(http(s)?:\/\/|\/)/.test(match[0]) ? match[0] : 'http://' + match[0];
$link = $("<a href=\"" + uri + "\" rel=\"nofollow\"></a>").text(match[0]);
replaceEls.push($link[0]);
}
replaceEls.push(document.createTextNode(text.substring(lastIndex)));
$node.replaceWith($(replaceEls));
}
return $el;
};
Formatter.prototype.format = function($el) {
var $node, blockNode, k, l, len, len1, n, node, ref, ref1;
if ($el == null) {
$el = this.editor.body;
}
if ($el.is(':empty')) {
$el.append('<p>' + this.editor.util.phBr + '</p>');
return $el;
}
ref = $el.contents();
for (k = 0, len = ref.length; k < len; k++) {
n = ref[k];
this.cleanNode(n, true);
}
ref1 = $el.contents();
for (l = 0, len1 = ref1.length; l < len1; l++) {
node = ref1[l];
$node = $(node);
if ($node.is('br')) {
if (typeof blockNode !== "undefined" && blockNode !== null) {
blockNode = null;
}
$node.remove();
} else if (this.editor.util.isBlockNode(node)) {
if ($node.is('li')) {
if (blockNode && blockNode.is('ul, ol')) {
blockNode.append(node);
} else {
blockNode = $('<ul/>').insertBefore(node);
blockNode.append(node);
}
} else {
blockNode = null;
}
} else {
if (!blockNode || blockNode.is('ul, ol')) {
blockNode = $('<p/>').insertBefore(node);
}
blockNode.append(node);
if (this.editor.util.isEmptyNode(blockNode)) {
blockNode.append(this.editor.util.phBr);
}
}
}
return $el;
};
Formatter.prototype.cleanNode = function(node, recursive) {
var $blockEls, $childImg, $node, $p, $td, allowedAttributes, attr, contents, isDecoration, k, l, len, len1, n, ref, ref1, text, textNode;
$node = $(node);
if (!($node.length > 0)) {
return;
}
if ($node[0].nodeType === 3) {
text = $node.text().replace(/(\r\n|\n|\r)/gm, '');
if (text) {
textNode = document.createTextNode(text);
$node.replaceWith(textNode);
} else {
$node.remove();
}
return;
}
contents = $node.is('iframe') ? null : $node.contents();
isDecoration = this.editor.util.isDecoratedNode($node);
if ($node.is(this._allowedTags.join(',')) || isDecoration) {
if ($node.is('a') && ($childImg = $node.find('img')).length > 0) {
$node.replaceWith($childImg);
$node = $childImg;
contents = null;
}
if ($node.is('td') && ($blockEls = $node.find(this.editor.util.blockNodes.join(','))).length > 0) {
$blockEls.each((function(_this) {
return function(i, blockEl) {
return $(blockEl).contents().unwrap();
};
})(this));
contents = $node.contents();
}
if ($node.is('img') && $node.hasClass('uploading')) {
$node.remove();
}
if (!isDecoration) {
allowedAttributes = this._allowedAttributes[$node[0].tagName.toLowerCase()];
ref = $.makeArray($node[0].attributes);
for (k = 0, len = ref.length; k < len; k++) {
attr = ref[k];
if (attr.name === 'style') {
continue;
}
if (!((allowedAttributes != null) && (ref1 = attr.name, indexOf.call(allowedAttributes, ref1) >= 0))) {
$node.removeAttr(attr.name);
}
}
this._cleanNodeStyles($node);
if ($node.is('span')) {
if ($node[0].attributes.length === 0) {
$node.contents().first().unwrap();
}
if ($node[0].style.length === 2 && $node[0].style.color === 'rgb(51, 51, 51)' && $node[0].style.fontSize === '16px') {
$node.contents().unwrap();
}
}
}
} else if ($node[0].nodeType === 1 && !$node.is(':empty')) {
if ($node.is('div, article, dl, header, footer, tr')) {
$node.append('<br/>');
contents.first().unwrap();
} else if ($node.is('table')) {
$p = $('<p/>');
$node.find('tr').each(function(i, tr) {
return $p.append($(tr).text() + '<br/>');
});
$node.replaceWith($p);
contents = null;
} else if ($node.is('thead, tfoot')) {
$node.remove();
contents = null;
} else if ($node.is('th')) {
$td = $('<td/>').append($node.contents());
$node.replaceWith($td);
} else {
contents.first().unwrap();
}
} else {
$node.remove();
contents = null;
}
if (recursive && (contents != null) && !$node.is('pre')) {
for (l = 0, len1 = contents.length; l < len1; l++) {
n = contents[l];
this.cleanNode(n, true);
}
}
return null;
};
Formatter.prototype._cleanNodeStyles = function($node) {
var allowedStyles, k, len, pair, ref, ref1, style, styleStr, styles;
styleStr = $node.attr('style');
if (!styleStr) {
return;
}
$node.removeAttr('style');
allowedStyles = this._allowedStyles[$node[0].tagName.toLowerCase()];
if (!(allowedStyles && allowedStyles.length > 0)) {
return $node;
}
styles = {};
ref = styleStr.split(';');
for (k = 0, len = ref.length; k < len; k++) {
style = ref[k];
style = $.trim(style);
pair = style.split(':');
if (pair.length !== 2) {
continue;
}
if (pair[0] === 'font-size' && pair[1].indexOf('px') > 0) {
if (parseInt(pair[1], 10) < 12) {
continue;
}
}
if (ref1 = pair[0], indexOf.call(allowedStyles, ref1) >= 0) {
styles[$.trim(pair[0])] = $.trim(pair[1]);
}
}
if (Object.keys(styles).length > 0) {
$node.css(styles);
}
return $node;
};
Formatter.prototype.clearHtml = function(html, lineBreak) {
var container, contents, result;
if (lineBreak == null) {
lineBreak = true;
}
container = $('<div/>').append(html);
contents = container.contents();
result = '';
contents.each((function(_this) {
return function(i, node) {
var $node, children;
if (node.nodeType === 3) {
return result += node.nodeValue;
} else if (node.nodeType === 1) {
$node = $(node);
children = $node.is('iframe') ? null : $node.contents();
if (children && children.length > 0) {
result += _this.clearHtml(children);
}
if (lineBreak && i < contents.length - 1 && $node.is('br, p, div, li,tr, pre, address, artticle, aside, dl, figcaption, footer, h1, h2,h3, h4, header')) {
return result += '\n';
}
}
};
})(this));
return result;
};
Formatter.prototype.beautify = function($contents) {
var uselessP;
uselessP = function($el) {
return !!($el.is('p') && !$el.text() && $el.children(':not(br)').length < 1);
};
return $contents.each(function(i, el) {
var $el, invalid;
$el = $(el);
invalid = $el.is(':not(img, br, col, td, hr, [class^="simditor-"]):empty');
if (invalid || uselessP($el)) {
$el.remove();
}
return $el.find(':not(img, br, col, td, hr, [class^="simditor-"]):empty').remove();
});
};
return Formatter;
})(SimpleModule);
InputManager = (function(superClass) {
extend(InputManager, superClass);
function InputManager() {
return InputManager.__super__.constructor.apply(this, arguments);
}
InputManager.pluginName = 'InputManager';
InputManager.prototype._modifierKeys = [16, 17, 18, 91, 93, 224];
InputManager.prototype._arrowKeys = [37, 38, 39, 40];
InputManager.prototype._init = function() {
var selectAllKey, submitKey;
this.editor = this._module;
this.throttledValueChanged = this.editor.util.throttle((function(_this) {
return function(params) {
return setTimeout(function() {
return _this.editor.trigger('valuechanged', params);
}, 10);
};
})(this), 300);
this.throttledSelectionChanged = this.editor.util.throttle((function(_this) {
return function() {
return _this.editor.trigger('selectionchanged');
};
})(this), 50);
$(document).on('selectionchange.simditor' + this.editor.id, (function(_this) {
return function(e) {
var triggerEvent;
if (!(_this.focused && !_this.editor.clipboard.pasting)) {
return;
}
triggerEvent = function() {
if (_this._selectionTimer) {
clearTimeout(_this._selectionTimer);
_this._selectionTimer = null;
}
if (_this.editor.selection._selection.rangeCount > 0) {
return _this.throttledSelectionChanged();
} else {
return _this._selectionTimer = setTimeout(function() {
_this._selectionTimer = null;
if (_this.focused) {
return triggerEvent();
}
}, 10);
}
};
return triggerEvent();
};
})(this));
this.editor.on('valuechanged', (function(_this) {
return function() {
var $rootBlocks;
_this.lastCaretPosition = null;
$rootBlocks = _this.editor.body.children().filter(function(i, node) {
return _this.editor.util.isBlockNode(node);
});
if (_this.focused && $rootBlocks.length === 0) {
_this.editor.selection.save();
_this.editor.formatter.format();
_this.editor.selection.restore();
}
_this.editor.body.find('hr, pre, .simditor-table').each(function(i, el) {
var $el, formatted;
$el = $(el);
if ($el.parent().is('blockquote') || $el.parent()[0] === _this.editor.body[0]) {
formatted = false;
if ($el.next().length === 0) {
$('<p/>').append(_this.editor.util.phBr).insertAfter($el);
formatted = true;
}
if ($el.prev().length === 0) {
$('<p/>').append(_this.editor.util.phBr).insertBefore($el);
formatted = true;
}
if (formatted) {
return _this.throttledValueChanged();
}
}
});
_this.editor.body.find('pre:empty').append(_this.editor.util.phBr);
if (!_this.editor.util.support.onselectionchange && _this.focused) {
return _this.throttledSelectionChanged();
}
};
})(this));
this.editor.body.on('keydown', $.proxy(this._onKeyDown, this)).on('keypress', $.proxy(this._onKeyPress, this)).on('keyup', $.proxy(this._onKeyUp, this)).on('mouseup', $.proxy(this._onMouseUp, this)).on('focus', $.proxy(this._onFocus, this)).on('blur', $.proxy(this._onBlur, this)).on('drop', $.proxy(this._onDrop, this)).on('input', $.proxy(this._onInput, this));
if (this.editor.util.browser.firefox) {
this.editor.hotkeys.add('cmd+left', (function(_this) {
return function(e) {
e.preventDefault();
_this.editor.selection._selection.modify('move', 'backward', 'lineboundary');
return false;
};
})(this));
this.editor.hotkeys.add('cmd+right', (function(_this) {
return function(e) {
e.preventDefault();
_this.editor.selection._selection.modify('move', 'forward', 'lineboundary');
return false;
};
})(this));
selectAllKey = this.editor.util.os.mac ? 'cmd+a' : 'ctrl+a';
this.editor.hotkeys.add(selectAllKey, (function(_this) {
return function(e) {
var $children, firstBlock, lastBlock, range;
$children = _this.editor.body.children();
if (!($children.length > 0)) {
return;
}
firstBlock = $children.first().get(0);
lastBlock = $children.last().get(0);
range = document.createRange();
range.setStart(firstBlock, 0);
range.setEnd(lastBlock, _this.editor.util.getNodeLength(lastBlock));
_this.editor.selection.range(range);
return false;
};
})(this));
}
submitKey = this.editor.util.os.mac ? 'cmd+enter' : 'ctrl+enter';
return this.editor.hotkeys.add(submitKey, (function(_this) {
return function(e) {
_this.editor.sync();
_this.editor.el.closest('form').find('button:submit').click();
return false;
};
})(this));
};
InputManager.prototype._onFocus = function(e) {
if (this.editor.clipboard.pasting) {
return;
}
this.editor.el.addClass('focus').removeClass('error');
this.focused = true;
return setTimeout((function(_this) {
return function() {
var $blockEl, range;
range = _this.editor.selection._selection.getRangeAt(0);
if (range.startContainer === _this.editor.body[0]) {
if (_this.lastCaretPosition) {
_this.editor.undoManager.caretPosition(_this.lastCaretPosition);
} else {
$blockEl = _this.editor.body.children().first();
range = document.createRange();
_this.editor.selection.setRangeAtStartOf($blockEl, range);
}
}
_this.lastCaretPosition = null;
_this.editor.triggerHandler('focus');
if (!_this.editor.util.support.onselectionchange) {
return _this.throttledSelectionChanged();
}
};
})(this), 0);
};
InputManager.prototype._onBlur = function(e) {
var ref;
if (this.editor.clipboard.pasting) {
return;
}
this.editor.el.removeClass('focus');
this.editor.sync();
this.focused = false;
this.lastCaretPosition = (ref = this.editor.undoManager.currentState()) != null ? ref.caret : void 0;
return this.editor.triggerHandler('blur');
};
InputManager.prototype._onMouseUp = function(e) {
if (!this.editor.util.support.onselectionchange) {
return this.throttledSelectionChanged();
}
};
InputManager.prototype._onKeyDown = function(e) {
var ref, ref1;
if (this.editor.triggerHandler(e) === false) {
return false;
}
if (this.editor.hotkeys.respondTo(e)) {
return;
}
if (this.editor.keystroke.respondTo(e)) {
this.throttledValueChanged();
return false;
}
if ((ref = e.which, indexOf.call(this._modifierKeys, ref) >= 0) || (ref1 = e.which, indexOf.call(this._arrowKeys, ref1) >= 0)) {
return;
}
if (this.editor.util.metaKey(e) && e.which === 86) {
return;
}
if (!this.editor.util.support.oninput) {
this.throttledValueChanged(['typing']);
}
return null;
};
InputManager.prototype._onKeyPress = function(e) {
if (this.editor.triggerHandler(e) === false) {
return false;
}
};
InputManager.prototype._onKeyUp = function(e) {
var p, ref;
if (this.editor.triggerHandler(e) === false) {
return false;
}
if (!this.editor.util.support.onselectionchange && (ref = e.which, indexOf.call(this._arrowKeys, ref) >= 0)) {
this.throttledValueChanged();
return;
}
if ((e.which === 8 || e.which === 46) && this.editor.util.isEmptyNode(this.editor.body)) {
this.editor.body.empty();
p = $('<p/>').append(this.editor.util.phBr).appendTo(this.editor.body);
this.editor.selection.setRangeAtStartOf(p);
}
};
InputManager.prototype._onDrop = function(e) {
if (this.editor.triggerHandler(e) === false) {
return false;
}
return this.throttledValueChanged();
};
InputManager.prototype._onInput = function(e) {
return this.throttledValueChanged(['oninput']);
};
return InputManager;
})(SimpleModule);
Keystroke = (function(superClass) {
extend(Keystroke, superClass);
function Keystroke() {
return Keystroke.__super__.constructor.apply(this, arguments);
}
Keystroke.pluginName = 'Keystroke';
Keystroke.prototype._init = function() {
this.editor = this._module;
this._keystrokeHandlers = {};
return this._initKeystrokeHandlers();
};
Keystroke.prototype.add = function(key, node, handler) {
key = key.toLowerCase();
key = this.editor.hotkeys.constructor.aliases[key] || key;
if (!this._keystrokeHandlers[key]) {
this._keystrokeHandlers[key] = {};
}
return this._keystrokeHandlers[key][node] = handler;
};
Keystroke.prototype.respondTo = function(e) {
var base, key, ref, result;
key = (ref = this.editor.hotkeys.constructor.keyNameMap[e.which]) != null ? ref.toLowerCase() : void 0;
if (!key) {
return;
}
if (key in this._keystrokeHandlers) {
result = typeof (base = this._keystrokeHandlers[key])['*'] === "function" ? base['*'](e) : void 0;
if (!result) {
this.editor.selection.startNodes().each((function(_this) {
return function(i, node) {
var handler, ref1;
if (node.nodeType !== Node.ELEMENT_NODE) {
return;
}
handler = (ref1 = _this._keystrokeHandlers[key]) != null ? ref1[node.tagName.toLowerCase()] : void 0;
result = typeof handler === "function" ? handler(e, $(node)) : void 0;
if (result === true || result === false) {
return false;
}
};
})(this));
}
if (result) {
return true;
}
}
};
Keystroke.prototype._initKeystrokeHandlers = function() {
var titleEnterHandler;
if (this.editor.util.browser.safari) {
this.add('enter', '*', (function(_this) {
return function(e) {
var $blockEl, $br;
if (!e.shiftKey) {
return;
}
$blockEl = _this.editor.selection.blockNodes().last();
if ($blockEl.is('pre')) {
return;
}
$br = $('<br/>');
if (_this.editor.selection.rangeAtEndOf($blockEl)) {
_this.editor.selection.insertNode($br);
_this.editor.selection.insertNode($('<br/>'));
_this.editor.selection.setRangeBefore($br);
} else {
_this.editor.selection.insertNode($br);
}
return true;
};
})(this));
}
if (this.editor.util.browser.webkit || this.editor.util.browser.msie) {
titleEnterHandler = (function(_this) {
return function(e, $node) {
var $p;
if (!_this.editor.selection.rangeAtEndOf($node)) {
return;
}
$p = $('<p/>').append(_this.editor.util.phBr).insertAfter($node);
_this.editor.selection.setRangeAtStartOf($p);
return true;
};
})(this);
this.add('enter', 'h1', titleEnterHandler);
this.add('enter', 'h2', titleEnterHandler);
this.add('enter', 'h3', titleEnterHandler);
this.add('enter', 'h4', titleEnterHandler);
this.add('enter', 'h5', titleEnterHandler);
this.add('enter', 'h6', titleEnterHandler);
}
this.add('backspace', '*', (function(_this) {
return function(e) {
var $blockEl, $prevBlockEl, $rootBlock, isWebkit;
$rootBlock = _this.editor.selection.rootNodes().first();
$prevBlockEl = $rootBlock.prev();
if ($prevBlockEl.is('hr') && _this.editor.selection.rangeAtStartOf($rootBlock)) {
_this.editor.selection.save();
$prevBlockEl.remove();
_this.editor.selection.restore();
return true;
}
$blockEl = _this.editor.selection.blockNodes().last();
if ($blockEl.is('.simditor-resize-handle') && $rootBlock.is('.simditor-table')) {
e.preventDefault();
$rootBlock.remove();
_this.editor.selection.setRangeAtEndOf($prevBlockEl);
}
if ($prevBlockEl.is('.simditor-table') && !$blockEl.is('table') && _this.editor.util.isEmptyNode($blockEl)) {
e.preventDefault();
$blockEl.remove();
_this.editor.selection.setRangeAtEndOf($prevBlockEl);
}
isWebkit = _this.editor.util.browser.webkit;
if (isWebkit && _this.editor.selection.rangeAtStartOf($blockEl)) {
_this.editor.selection.save();
_this.editor.formatter.cleanNode($blockEl, true);
_this.editor.selection.restore();
return null;
}
};
})(this));
this.add('enter', 'div', (function(_this) {
return function(e, $node) {
var $blockEl, $p;
if ($node.is('.simditor-table')) {
$blockEl = _this.editor.selection.blockNodes().last();
if ($blockEl.is('.simditor-resize-handle')) {
e.preventDefault();
$p = $('<p/>').append(_this.editor.util.phBr).insertAfter($node);
return _this.editor.selection.setRangeAtStartOf($p);
}
}
};
})(this));
this.add('enter', 'li', (function(_this) {
return function(e, $node) {
var $cloneNode, listEl, newBlockEl, newListEl;
$cloneNode = $node.clone();
$cloneNode.find('ul, ol').remove();
if (!(_this.editor.util.isEmptyNode($cloneNode) && $node.is(_this.editor.selection.blockNodes().last()))) {
return;
}
listEl = $node.parent();
if ($node.next('li').length > 0) {
if (!_this.editor.util.isEmptyNode($node)) {
return;
}
if (listEl.parent('li').length > 0) {
newBlockEl = $('<li/>').append(_this.editor.util.phBr).insertAfter(listEl.parent('li'));
newListEl = $('<' + listEl[0].tagName + '/>').append($node.nextAll('li'));
newBlockEl.append(newListEl);
} else {
newBlockEl = $('<p/>').append(_this.editor.util.phBr).insertAfter(listEl);
newListEl = $('<' + listEl[0].tagName + '/>').append($node.nextAll('li'));
newBlockEl.after(newListEl);
}
} else {
if (listEl.parent('li').length > 0) {
newBlockEl = $('<li/>').insertAfter(listEl.parent('li'));
if ($node.contents().length > 0) {
newBlockEl.append($node.contents());
} else {
newBlockEl.append(_this.editor.util.phBr);
}
} else {
newBlockEl = $('<p/>').append(_this.editor.util.phBr).insertAfter(listEl);
if ($node.children('ul, ol').length > 0) {
newBlockEl.after($node.children('ul, ol'));
}
}
}
if ($node.prev('li').length) {
$node.remove();
} else {
if ($node.prev('ul').length || $node.prev('ol').length) {
$node.remove();
} else {
listEl.remove();
}
}
_this.editor.selection.setRangeAtStartOf(newBlockEl);
return true;
};
})(this));
this.add('enter', 'pre', (function(_this) {
return function(e, $node) {
var $p, breakNode, range;
e.preventDefault();
if (e.shiftKey) {
$p = $('<p/>').append(_this.editor.util.phBr).insertAfter($node);
_this.editor.selection.setRangeAtStartOf($p);
return true;
}
range = _this.editor.selection.range();
breakNode = null;
range.deleteContents();
if (!_this.editor.util.browser.msie && _this.editor.selection.rangeAtEndOf($node)) {
breakNode = document.createTextNode('\n\n');
} else {
breakNode = document.createTextNode('\n');
}
range.insertNode(breakNode);
range.setEnd(breakNode, 1);
range.collapse(false);
_this.editor.selection.range(range);
return true;
};
})(this));
this.add('enter', 'blockquote', (function(_this) {
return function(e, $node) {
var $closestBlock, range;
$closestBlock = _this.editor.selection.blockNodes().last();
if (!($closestBlock.is('p') && !$closestBlock.next().length && _this.editor.util.isEmptyNode($closestBlock))) {
return;
}
$node.after($closestBlock);
range = document.createRange();
_this.editor.selection.setRangeAtStartOf($closestBlock, range);
return true;
};
})(this));
this.add('backspace', 'li', (function(_this) {
return function(e, $node) {
var $br, $childList, $newLi, $prevChildList, $prevNode, $textNode, isFF, range, text;
$childList = $node.children('ul, ol');
$prevNode = $node.prev('li');
if (!($childList.length > 0 && $prevNode.length > 0)) {
return false;
}
text = '';
$textNode = null;
$node.contents().each(function(i, n) {
if (n.nodeType === 1 && /UL|OL/.test(n.nodeName)) {
return false;
}
if (n.nodeType === 1 && /BR/.test(n.nodeName)) {
return;
}
if (n.nodeType === 3 && n.nodeValue) {
text += n.nodeValue;
} else if (n.nodeType === 1) {
text += $(n).text();
}
return $textNode = $(n);
});
isFF = _this.editor.util.browser.firefox && !$textNode.next('br').length;
if ($textNode && text.length === 1 && isFF) {
$br = $(_this.editor.util.phBr).insertAfter($textNode);
$textNode.remove();
_this.editor.selection.setRangeBefore($br);
return true;
} else if (text.length > 0) {
return false;
}
range = document.createRange();
$prevChildList = $prevNode.children('ul, ol');
if ($prevChildList.length > 0) {
$newLi = $('<li/>').append(_this.editor.util.phBr).appendTo($prevChildList);
$prevChildList.append($childList.children('li'));
$node.remove();
_this.editor.selection.setRangeAtEndOf($newLi, range);
} else {
_this.editor.selection.setRangeAtEndOf($prevNode, range);
$prevNode.append($childList);
$node.remove();
_this.editor.selection.range(range);
}
return true;
};
})(this));
this.add('backspace', 'pre', (function(_this) {
return function(e, $node) {
var $newNode, codeStr, range;
if (!_this.editor.selection.rangeAtStartOf($node)) {
return;
}
codeStr = $node.html().replace('\n', '<br/>') || _this.editor.util.phBr;
$newNode = $('<p/>').append(codeStr).insertAfter($node);
$node.remove();
range = document.createRange();
_this.editor.selection.setRangeAtStartOf($newNode, range);
return true;
};
})(this));
return this.add('backspace', 'blockquote', (function(_this) {
return function(e, $node) {
var $firstChild, range;
if (!_this.editor.selection.rangeAtStartOf($node)) {
return;
}
$firstChild = $node.children().first().unwrap();
range = document.createRange();
_this.editor.selection.setRangeAtStartOf($firstChild, range);
return true;
};
})(this));
};
return Keystroke;
})(SimpleModule);
UndoManager = (function(superClass) {
extend(UndoManager, superClass);
function UndoManager() {
return UndoManager.__super__.constructor.apply(this, arguments);
}
UndoManager.pluginName = 'UndoManager';
UndoManager.prototype._index = -1;
UndoManager.prototype._capacity = 20;
UndoManager.prototype._startPosition = null;
UndoManager.prototype._endPosition = null;
UndoManager.prototype._init = function() {
var redoShortcut, undoShortcut;
this.editor = this._module;
this._stack = [];
if (this.editor.util.os.mac) {
undoShortcut = 'cmd+z';
redoShortcut = 'shift+cmd+z';
} else if (this.editor.util.os.win) {
undoShortcut = 'ctrl+z';
redoShortcut = 'ctrl+y';
} else {
undoShortcut = 'ctrl+z';
redoShortcut = 'shift+ctrl+z';
}
this.editor.hotkeys.add(undoShortcut, (function(_this) {
return function(e) {
e.preventDefault();
_this.undo();
return false;
};
})(this));
this.editor.hotkeys.add(redoShortcut, (function(_this) {
return function(e) {
e.preventDefault();
_this.redo();
return false;
};
})(this));
this.throttledPushState = this.editor.util.throttle((function(_this) {
return function() {
return _this._pushUndoState();
};
})(this), 2000);
this.editor.on('valuechanged', (function(_this) {
return function(e, src) {
if (src === 'undo' || src === 'redo') {
return;
}
return _this.throttledPushState();
};
})(this));
this.editor.on('selectionchanged', (function(_this) {
return function(e) {
_this.resetCaretPosition();
return _this.update();
};
})(this));
this.editor.on('focus', (function(_this) {
return function(e) {
if (_this._stack.length === 0) {
return _this._pushUndoState();
}
};
})(this));
return this.editor.on('blur', (function(_this) {
return function(e) {
return _this.resetCaretPosition();
};
})(this));
};
UndoManager.prototype.resetCaretPosition = function() {
this._startPosition = null;
return this._endPosition = null;
};
UndoManager.prototype.startPosition = function() {
if (this.editor.selection._range) {
this._startPosition || (this._startPosition = this._getPosition('start'));
}
return this._startPosition;
};
UndoManager.prototype.endPosition = function() {
if (this.editor.selection._range) {
this._endPosition || (this._endPosition = (function(_this) {
return function() {
var range;
range = _this.editor.selection.range();
if (range.collapsed) {
return _this._startPosition;
}
return _this._getPosition('end');
};
})(this)());
}
return this._endPosition;
};
UndoManager.prototype._pushUndoState = function() {
var caret;
if (this.editor.triggerHandler('pushundostate') === false) {
return;
}
caret = this.caretPosition();
if (!caret.start) {
return;
}
this._index += 1;
this._stack.length = this._index;
this._stack.push({
html: this.editor.body.html(),
caret: this.caretPosition()
});
if (this._stack.length > this._capacity) {
this._stack.shift();
return this._index -= 1;
}
};
UndoManager.prototype.currentState = function() {
if (this._stack.length && this._index > -1) {
return this._stack[this._index];
} else {
return null;
}
};
UndoManager.prototype.undo = function() {
var state;
if (this._index < 1 || this._stack.length < 2) {
return;
}
this.editor.hidePopover();
this._index -= 1;
state = this._stack[this._index];
this.editor.body.get(0).innerHTML = state.html;
this.caretPosition(state.caret);
this.editor.body.find('.selected').removeClass('selected');
this.editor.sync();
return this.editor.trigger('valuechanged', ['undo']);
};
UndoManager.prototype.redo = function() {
var state;
if (this._index < 0 || this._stack.length < this._index + 2) {
return;
}
this.editor.hidePopover();
this._index += 1;
state = this._stack[this._index];
this.editor.body.get(0).innerHTML = state.html;
this.caretPosition(state.caret);
this.editor.body.find('.selected').removeClass('selected');
this.editor.sync();
return this.editor.trigger('valuechanged', ['redo']);
};
UndoManager.prototype.update = function() {
var currentState;
currentState = this.currentState();
if (!currentState) {
return;
}
currentState.html = this.editor.body.html();
return currentState.caret = this.caretPosition();
};
UndoManager.prototype._getNodeOffset = function(node, index) {
var $parent, merging, offset;
if ($.isNumeric(index)) {
$parent = $(node);
} else {
$parent = $(node).par