UNPKG

hdjs

Version:
1,511 lines (1,420 loc) 181 kB
(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