From 538580d787a0a2b98e3ec02ee7179d4ef29c9b85 Mon Sep 17 00:00:00 2001 From: Summer Date: Fri, 20 Sep 2019 00:38:40 +0000 Subject: [PATCH] =?UTF-8?q?WYSIWYG=20=E7=BC=96=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes public/css/.DS_Store | Bin 0 -> 6148 bytes public/css/simditor.css | 746 +++ public/js/hotkeys.js | 241 + public/js/module.js | 172 + public/js/simditor.js | 5585 +++++++++++++++++ public/js/uploader.js | 261 + resources/.DS_Store | Bin 0 -> 6148 bytes resources/editor/.DS_Store | Bin 0 -> 8196 bytes resources/editor/css/.DS_Store | Bin 0 -> 6148 bytes resources/editor/css/simditor.css | 746 +++ resources/editor/js/hotkeys.js | 241 + resources/editor/js/module.js | 172 + resources/editor/js/simditor.js | 5585 +++++++++++++++++ resources/editor/js/uploader.js | 261 + resources/views/layouts/app.blade.php | 5 + .../views/topics/create_and_edit.blade.php | 20 + webpack.mix.js | 5 +- 18 files changed, 14039 insertions(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 public/css/.DS_Store create mode 100644 public/css/simditor.css create mode 100644 public/js/hotkeys.js create mode 100644 public/js/module.js create mode 100644 public/js/simditor.js create mode 100644 public/js/uploader.js create mode 100644 resources/.DS_Store create mode 100644 resources/editor/.DS_Store create mode 100644 resources/editor/css/.DS_Store create mode 100644 resources/editor/css/simditor.css create mode 100644 resources/editor/js/hotkeys.js create mode 100644 resources/editor/js/module.js create mode 100644 resources/editor/js/simditor.js create mode 100644 resources/editor/js/uploader.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..53fb051541bba9bee2ee9b7c7c1e1cf7111a9512 GIT binary patch literal 6148 zcmeHKI}XAy47Gs)#KOp!D{zAd!3nqkg0dl10H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 textarea { + display: none !important; + width: 100%; + box-sizing: border-box; + font-family: monaco; + font-size: 16px; + line-height: 1.6; + border: none; + padding: 22px 15px 40px; + min-height: 300px; + outline: none; + background: transparent; + resize: none; +} +.simditor .simditor-wrapper .simditor-placeholder { + display: none; + position: absolute; + left: 0; + z-index: 0; + padding: 22px 15px; + font-size: 16px; + font-family: arial, sans-serif; + line-height: 1.5; + color: #999999; + background: transparent; +} +.simditor .simditor-wrapper.toolbar-floating .simditor-toolbar { + position: fixed; + top: 0; + z-index: 10; + box-shadow: 0 0 6px rgba(0, 0, 0, 0.1); +} +.simditor .simditor-wrapper .simditor-image-loading { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 2; +} +.simditor .simditor-wrapper .simditor-image-loading .progress { + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.4); + position: absolute; + bottom: 0; + left: 0; +} +.simditor .simditor-body { + padding: 22px 15px 40px; + min-height: 300px; + outline: none; + cursor: text; + position: relative; + z-index: 1; + background: transparent; +} +.simditor .simditor-body a.selected { + background: #b3d4fd; +} +.simditor .simditor-body a.simditor-mention { + cursor: pointer; +} +.simditor .simditor-body .simditor-table { + position: relative; +} +.simditor .simditor-body .simditor-table.resizing { + cursor: col-resize; +} +.simditor .simditor-body .simditor-table .simditor-resize-handle { + position: absolute; + left: 0; + top: 0; + width: 10px; + height: 100%; + cursor: col-resize; +} +.simditor .simditor-body pre { + /*min-height: 28px;*/ + box-sizing: border-box; + -moz-box-sizing: border-box; + word-wrap: break-word !important; + white-space: pre-wrap !important; +} +.simditor .simditor-body img { + cursor: pointer; +} +.simditor .simditor-body img.selected { + box-shadow: 0 0 0 4px #cccccc; +} +.simditor .simditor-paste-bin { + position: fixed; + bottom: 10px; + right: 10px; + width: 1px; + height: 20px; + font-size: 1px; + line-height: 1px; + overflow: hidden; + padding: 0; + margin: 0; + opacity: 0; + -webkit-user-select: text; +} +.simditor .simditor-toolbar { + border-bottom: 1px solid #eeeeee; + background: #ffffff; + width: 100%; +} +.simditor .simditor-toolbar > ul { + margin: 0; + padding: 0 0 0 6px; + list-style: none; +} +.simditor .simditor-toolbar > ul > li { + position: relative; + display: inline-block; + font-size: 0; +} +.simditor .simditor-toolbar > ul > li > span.separator { + display: inline-block; + background: #cfcfcf; + width: 1px; + height: 18px; + margin: 11px 15px; + vertical-align: middle; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item { + display: inline-block; + width: 46px; + height: 40px; + outline: none; + color: #333333; + font-size: 15px; + line-height: 40px; + vertical-align: middle; + text-align: center; + text-decoration: none; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item span { + opacity: 0.6; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item span.simditor-icon { + display: inline; + line-height: normal; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item:hover span { + opacity: 1; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.active { + background: #eeeeee; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.active span { + opacity: 1; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled { + cursor: default; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled span { + opacity: 0.3; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title span:before { + content: "H"; + font-size: 19px; + font-weight: bold; + font-family: 'Times New Roman'; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h1 span:before { + content: 'H1'; + font-size: 18px; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h2 span:before { + content: 'H2'; + font-size: 18px; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h3 span:before { + content: 'H3'; + font-size: 18px; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-image { + position: relative; + overflow: hidden; +} +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-image > input[type=file] { + position: absolute; + right: 0px; + top: 0px; + opacity: 0; + font-size: 100px; + cursor: pointer; +} +.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item { + position: relative; + z-index: 20; + background: #ffffff; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} +.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item span { + opacity: 1; +} +.simditor .simditor-toolbar > ul > li.menu-on .toolbar-menu { + display: block; +} +.simditor .simditor-toolbar .toolbar-menu { + display: none; + position: absolute; + top: 40px; + left: 0; + z-index: 21; + background: #ffffff; + text-align: left; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); +} +.simditor .simditor-toolbar .toolbar-menu:before { + content: ''; + display: block; + width: 46px; + height: 4px; + background: #ffffff; + position: absolute; + top: -3px; + left: 0; +} +.simditor .simditor-toolbar .toolbar-menu ul { + min-width: 160px; + list-style: none; + margin: 0; + padding: 10px 1px; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item { + display: block; + font-size: 16px; + line-height: 2em; + padding: 0 10px; + text-decoration: none; + color: #666666; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item:hover { + background: #f6f6f6; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h1 { + font-size: 24px; + color: #333333; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h2 { + font-size: 22px; + color: #333333; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h3 { + font-size: 20px; + color: #333333; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h4 { + font-size: 18px; + color: #333333; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h5 { + font-size: 16px; + color: #333333; +} +.simditor .simditor-toolbar .toolbar-menu ul > li .separator { + display: block; + border-top: 1px solid #cccccc; + height: 0; + line-height: 0; + font-size: 0; + margin: 6px 0; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color { + width: 96px; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list { + height: 40px; + margin: 10px 6px 6px 10px; + padding: 0; + min-width: 0; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li { + float: left; + margin: 0 4px 4px 0; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color { + display: block; + width: 16px; + height: 16px; + background: #dfdfdf; + border-radius: 2px; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color:hover { + opacity: 0.8; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color.font-color-default { + background: #333333; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-1 { + background: #E33737; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-2 { + background: #e28b41; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-3 { + background: #c8a732; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-4 { + background: #209361; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-5 { + background: #418caf; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-6 { + background: #aa8773; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-7 { + background: #999999; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table { + background: #ffffff; + padding: 1px; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table { + border: none; + border-collapse: collapse; + border-spacing: 0; + table-layout: fixed; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td { + padding: 0; + cursor: pointer; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td:before { + width: 16px; + height: 16px; + border: 1px solid #ffffff; + background: #f3f3f3; + display: block; + content: ""; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td.selected:before { + background: #cfcfcf; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table { + display: none; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table ul li { + white-space: nowrap; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image { + position: relative; + overflow: hidden; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image input[type=file] { + position: absolute; + right: 0px; + top: 0px; + opacity: 0; + font-size: 100px; + cursor: pointer; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment { + width: 100%; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment ul { + min-width: 100%; +} +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment .menu-item { + text-align: center; +} +.simditor .simditor-popover { + display: none; + padding: 5px 8px 0; + background: #ffffff; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + border-radius: 2px; + position: absolute; + z-index: 2; +} +.simditor .simditor-popover .settings-field { + margin: 0 0 5px 0; + font-size: 12px; + height: 25px; + line-height: 25px; +} +.simditor .simditor-popover .settings-field label { + display: inline-block; + margin: 0 5px 0 0; +} +.simditor .simditor-popover .settings-field input[type=text] { + display: inline-block; + width: 200px; + box-sizing: border-box; + font-size: 12px; +} +.simditor .simditor-popover .settings-field input[type=text].image-size { + width: 83px; +} +.simditor .simditor-popover .settings-field .times { + display: inline-block; + width: 26px; + font-size: 12px; + text-align: center; +} +.simditor .simditor-popover.link-popover .btn-unlink, .simditor .simditor-popover.image-popover .btn-upload, .simditor .simditor-popover.image-popover .btn-restore { + display: inline-block; + margin: 0 0 0 5px; + color: #333333; + font-size: 14px; + outline: 0; +} +.simditor .simditor-popover.link-popover .btn-unlink span, .simditor .simditor-popover.image-popover .btn-upload span, .simditor .simditor-popover.image-popover .btn-restore span { + opacity: 0.6; +} +.simditor .simditor-popover.link-popover .btn-unlink:hover span, .simditor .simditor-popover.image-popover .btn-upload:hover span, .simditor .simditor-popover.image-popover .btn-restore:hover span { + opacity: 1; +} +.simditor .simditor-popover.image-popover .btn-upload { + position: relative; + display: inline-block; + overflow: hidden; + vertical-align: middle; +} +.simditor .simditor-popover.image-popover .btn-upload input[type=file] { + position: absolute; + right: 0px; + top: 0px; + opacity: 0; + height: 100%; + width: 28px; +} +.simditor.simditor-mobile .simditor-wrapper.toolbar-floating .simditor-toolbar { + position: absolute; + top: 0; + z-index: 10; + box-shadow: 0 0 6px rgba(0, 0, 0, 0.1); +} + +.simditor .simditor-body, .editor-style { + font-size: 16px; + font-family: arial, sans-serif; + line-height: 1.6; + color: #333; + outline: none; + word-wrap: break-word; +} +.simditor .simditor-body > :first-child, .editor-style > :first-child { + margin-top: 0 !important; +} +.simditor .simditor-body a, .editor-style a { + color: #4298BA; + text-decoration: none; + word-break: break-all; +} +.simditor .simditor-body a:visited, .editor-style a:visited { + color: #4298BA; +} +.simditor .simditor-body a:hover, .editor-style a:hover { + color: #0F769F; +} +.simditor .simditor-body a:active, .editor-style a:active { + color: #9E792E; +} +.simditor .simditor-body a:hover, .simditor .simditor-body a:active, .editor-style a:hover, .editor-style a:active { + outline: 0; +} +.simditor .simditor-body h1, .simditor .simditor-body h2, .simditor .simditor-body h3, .simditor .simditor-body h4, .simditor .simditor-body h5, .simditor .simditor-body h6, .editor-style h1, .editor-style h2, .editor-style h3, .editor-style h4, .editor-style h5, .editor-style h6 { + font-weight: normal; + margin: 40px 0 20px; + color: #000000; +} +.simditor .simditor-body h1, .editor-style h1 { + font-size: 24px; +} +.simditor .simditor-body h2, .editor-style h2 { + font-size: 22px; +} +.simditor .simditor-body h3, .editor-style h3 { + font-size: 20px; +} +.simditor .simditor-body h4, .editor-style h4 { + font-size: 18px; +} +.simditor .simditor-body h5, .editor-style h5 { + font-size: 16px; +} +.simditor .simditor-body h6, .editor-style h6 { + font-size: 16px; +} +.simditor .simditor-body p, .simditor .simditor-body div, .editor-style p, .editor-style div { + word-wrap: break-word; + margin: 0 0 15px 0; + color: #333; + word-wrap: break-word; +} +.simditor .simditor-body b, .simditor .simditor-body strong, .editor-style b, .editor-style strong { + font-weight: bold; +} +.simditor .simditor-body i, .simditor .simditor-body em, .editor-style i, .editor-style em { + font-style: italic; +} +.simditor .simditor-body u, .editor-style u { + text-decoration: underline; +} +.simditor .simditor-body strike, .simditor .simditor-body del, .editor-style strike, .editor-style del { + text-decoration: line-through; +} +.simditor .simditor-body ul, .simditor .simditor-body ol, .editor-style ul, .editor-style ol { + list-style: disc outside none; + margin: 15px 0; + padding: 0 0 0 40px; + line-height: 1.6; +} +.simditor .simditor-body ul ul, .simditor .simditor-body ul ol, .simditor .simditor-body ol ul, .simditor .simditor-body ol ol, .editor-style ul ul, .editor-style ul ol, .editor-style ol ul, .editor-style ol ol { + padding-left: 30px; +} +.simditor .simditor-body ul ul, .simditor .simditor-body ol ul, .editor-style ul ul, .editor-style ol ul { + list-style: circle outside none; +} +.simditor .simditor-body ul ul ul, .simditor .simditor-body ol ul ul, .editor-style ul ul ul, .editor-style ol ul ul { + list-style: square outside none; +} +.simditor .simditor-body ol, .editor-style ol { + list-style: decimal; +} +.simditor .simditor-body blockquote, .editor-style blockquote { + border-left: 6px solid #ddd; + padding: 5px 0 5px 10px; + margin: 15px 0 15px 15px; +} +.simditor .simditor-body blockquote > :first-child, .editor-style blockquote > :first-child { + margin-top: 0; +} +.simditor .simditor-body code, .editor-style code { + display: inline-block; + padding: 0 4px; + margin: 0 5px; + background: #eeeeee; + border-radius: 3px; + font-size: 13px; + font-family: 'monaco', 'Consolas', "Liberation Mono", Courier, monospace; +} +.simditor .simditor-body pre, .editor-style pre { + padding: 10px 5px 10px 10px; + margin: 15px 0; + display: block; + line-height: 18px; + background: #F0F0F0; + border-radius: 3px; + font-size: 13px; + font-family: 'monaco', 'Consolas', "Liberation Mono", Courier, monospace; + white-space: pre; + word-wrap: normal; + overflow-x: auto; +} +.simditor .simditor-body pre code, .editor-style pre code { + display: block; + padding: 0; + margin: 0; + background: none; + border-radius: 0; +} +.simditor .simditor-body hr, .editor-style hr { + display: block; + height: 0px; + border: 0; + border-top: 1px solid #ccc; + margin: 15px 0; + padding: 0; +} +.simditor .simditor-body table, .editor-style table { + width: 100%; + table-layout: fixed; + border-collapse: collapse; + border-spacing: 0; + margin: 15px 0; +} +.simditor .simditor-body table thead, .editor-style table thead { + background-color: #f9f9f9; +} +.simditor .simditor-body table td, .simditor .simditor-body table th, .editor-style table td, .editor-style table th { + min-width: 40px; + height: 30px; + border: 1px solid #ccc; + vertical-align: top; + padding: 2px 4px; + text-align: left; + box-sizing: border-box; +} +.simditor .simditor-body table td.active, .simditor .simditor-body table th.active, .editor-style table td.active, .editor-style table th.active { + background-color: #ffffee; +} +.simditor .simditor-body img, .editor-style img { + margin: 0 5px; + vertical-align: middle; +} diff --git a/public/js/hotkeys.js b/public/js/hotkeys.js new file mode 100644 index 000000000..de20b918c --- /dev/null +++ b/public/js/hotkeys.js @@ -0,0 +1,241 @@ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module unless amdModuleId is set + define('simple-hotkeys', ["jquery","simple-module"], function ($, SimpleModule) { + return (root['hotkeys'] = factory($, SimpleModule)); + }); + } 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")); + } else { + root.simple = root.simple || {}; + root.simple['hotkeys'] = factory(jQuery,SimpleModule); + } +}(this, function ($, SimpleModule) { + +var Hotkeys, hotkeys, + 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; + +Hotkeys = (function(superClass) { + extend(Hotkeys, superClass); + + function Hotkeys() { + return Hotkeys.__super__.constructor.apply(this, arguments); + } + + Hotkeys.count = 0; + + Hotkeys.keyNameMap = { + 8: "Backspace", + 9: "Tab", + 13: "Enter", + 16: "Shift", + 17: "Control", + 18: "Alt", + 19: "Pause", + 20: "CapsLock", + 27: "Esc", + 32: "Spacebar", + 33: "PageUp", + 34: "PageDown", + 35: "End", + 36: "Home", + 37: "Left", + 38: "Up", + 39: "Right", + 40: "Down", + 45: "Insert", + 46: "Del", + 91: "Meta", + 93: "Meta", + 48: "0", + 49: "1", + 50: "2", + 51: "3", + 52: "4", + 53: "5", + 54: "6", + 55: "7", + 56: "8", + 57: "9", + 65: "A", + 66: "B", + 67: "C", + 68: "D", + 69: "E", + 70: "F", + 71: "G", + 72: "H", + 73: "I", + 74: "J", + 75: "K", + 76: "L", + 77: "M", + 78: "N", + 79: "O", + 80: "P", + 81: "Q", + 82: "R", + 83: "S", + 84: "T", + 85: "U", + 86: "V", + 87: "W", + 88: "X", + 89: "Y", + 90: "Z", + 96: "0", + 97: "1", + 98: "2", + 99: "3", + 100: "4", + 101: "5", + 102: "6", + 103: "7", + 104: "8", + 105: "9", + 106: "Multiply", + 107: "Add", + 109: "Subtract", + 110: "Decimal", + 111: "Divide", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 124: "F13", + 125: "F14", + 126: "F15", + 127: "F16", + 128: "F17", + 129: "F18", + 130: "F19", + 131: "F20", + 132: "F21", + 133: "F22", + 134: "F23", + 135: "F24", + 59: ";", + 61: "=", + 186: ";", + 187: "=", + 188: ",", + 190: ".", + 191: "/", + 192: "`", + 219: "[", + 220: "\\", + 221: "]", + 222: "'" + }; + + Hotkeys.aliases = { + "escape": "esc", + "delete": "del", + "return": "enter", + "ctrl": "control", + "space": "spacebar", + "ins": "insert", + "cmd": "meta", + "command": "meta", + "wins": "meta", + "windows": "meta" + }; + + Hotkeys.normalize = function(shortcut) { + var i, j, key, keyname, keys, len; + keys = shortcut.toLowerCase().replace(/\s+/gi, "").split("+"); + for (i = j = 0, len = keys.length; j < len; i = ++j) { + key = keys[i]; + keys[i] = this.aliases[key] || key; + } + keyname = keys.pop(); + keys.sort().push(keyname); + return keys.join("_"); + }; + + Hotkeys.prototype.opts = { + el: document + }; + + Hotkeys.prototype._init = function() { + this.id = ++this.constructor.count; + this._map = {}; + this._delegate = typeof this.opts.el === "string" ? document : this.opts.el; + return $(this._delegate).on("keydown.simple-hotkeys-" + this.id, this.opts.el, (function(_this) { + return function(e) { + var ref; + return (ref = _this._getHander(e)) != null ? ref.call(_this, e) : void 0; + }; + })(this)); + }; + + Hotkeys.prototype._getHander = function(e) { + var keyname, shortcut; + if (!(keyname = this.constructor.keyNameMap[e.which])) { + return; + } + shortcut = ""; + if (e.altKey) { + shortcut += "alt_"; + } + if (e.ctrlKey) { + shortcut += "control_"; + } + if (e.metaKey) { + shortcut += "meta_"; + } + if (e.shiftKey) { + shortcut += "shift_"; + } + shortcut += keyname.toLowerCase(); + return this._map[shortcut]; + }; + + Hotkeys.prototype.respondTo = function(subject) { + if (typeof subject === 'string') { + return this._map[this.constructor.normalize(subject)] != null; + } else { + return this._getHander(subject) != null; + } + }; + + Hotkeys.prototype.add = function(shortcut, handler) { + this._map[this.constructor.normalize(shortcut)] = handler; + return this; + }; + + Hotkeys.prototype.remove = function(shortcut) { + delete this._map[this.constructor.normalize(shortcut)]; + return this; + }; + + Hotkeys.prototype.destroy = function() { + $(this._delegate).off(".simple-hotkeys-" + this.id); + this._map = {}; + return this; + }; + + return Hotkeys; + +})(SimpleModule); + +hotkeys = function(opts) { + return new Hotkeys(opts); +}; + +return hotkeys; + +})); + diff --git a/public/js/module.js b/public/js/module.js new file mode 100644 index 000000000..9f7dbbd7c --- /dev/null +++ b/public/js/module.js @@ -0,0 +1,172 @@ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module unless amdModuleId is set + define('simple-module', ["jquery"], function (a0) { + return (root['Module'] = factory(a0)); + }); + } 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")); + } else { + root['SimpleModule'] = factory(jQuery); + } +}(this, function ($) { + +var Module, + slice = [].slice; + +Module = (function() { + Module.extend = function(obj) { + var key, ref, val; + if (!((obj != null) && typeof obj === 'object')) { + return; + } + for (key in obj) { + val = obj[key]; + if (key !== 'included' && key !== 'extended') { + this[key] = val; + } + } + return (ref = obj.extended) != null ? ref.call(this) : void 0; + }; + + Module.include = function(obj) { + var key, ref, val; + if (!((obj != null) && typeof obj === 'object')) { + return; + } + for (key in obj) { + val = obj[key]; + if (key !== 'included' && key !== 'extended') { + this.prototype[key] = val; + } + } + return (ref = obj.included) != null ? ref.call(this) : void 0; + }; + + Module.connect = function(cls) { + if (typeof cls !== 'function') { + return; + } + if (!cls.pluginName) { + throw new Error('Module.connect: cannot connect plugin without pluginName'); + return; + } + cls.prototype._connected = true; + if (!this._connectedClasses) { + this._connectedClasses = []; + } + this._connectedClasses.push(cls); + if (cls.pluginName) { + return this[cls.pluginName] = cls; + } + }; + + Module.prototype.opts = {}; + + function Module(opts) { + var base, cls, i, instance, instances, len, name; + this.opts = $.extend({}, this.opts, opts); + (base = this.constructor)._connectedClasses || (base._connectedClasses = []); + instances = (function() { + var i, len, ref, results; + ref = this.constructor._connectedClasses; + results = []; + for (i = 0, len = ref.length; i < len; i++) { + cls = ref[i]; + name = cls.pluginName.charAt(0).toLowerCase() + cls.pluginName.slice(1); + if (cls.prototype._connected) { + cls.prototype._module = this; + } + results.push(this[name] = new cls()); + } + return results; + }).call(this); + if (this._connected) { + this.opts = $.extend({}, this.opts, this._module.opts); + } else { + this._init(); + for (i = 0, len = instances.length; i < len; i++) { + instance = instances[i]; + if (typeof instance._init === "function") { + instance._init(); + } + } + } + this.trigger('initialized'); + } + + Module.prototype._init = function() {}; + + Module.prototype.on = function() { + var args, ref; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + (ref = $(this)).on.apply(ref, args); + return this; + }; + + Module.prototype.one = function() { + var args, ref; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + (ref = $(this)).one.apply(ref, args); + return this; + }; + + Module.prototype.off = function() { + var args, ref; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + (ref = $(this)).off.apply(ref, args); + return this; + }; + + Module.prototype.trigger = function() { + var args, ref; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + (ref = $(this)).trigger.apply(ref, args); + return this; + }; + + Module.prototype.triggerHandler = function() { + var args, ref; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return (ref = $(this)).triggerHandler.apply(ref, args); + }; + + Module.prototype._t = function() { + var args, ref; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return (ref = this.constructor)._t.apply(ref, args); + }; + + Module._t = function() { + var args, key, ref, result; + key = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + result = ((ref = this.i18n[this.locale]) != null ? ref[key] : void 0) || ''; + if (!(args.length > 0)) { + return result; + } + result = result.replace(/([^%]|^)%(?:(\d+)\$)?s/g, function(p0, p, position) { + if (position) { + return p + args[parseInt(position) - 1]; + } else { + return p + args.shift(); + } + }); + return result.replace(/%%s/g, '%s'); + }; + + Module.i18n = { + 'zh-CN': {} + }; + + Module.locale = 'zh-CN'; + + return Module; + +})(); + +return Module; + +})); diff --git a/public/js/simditor.js b/public/js/simditor.js new file mode 100644 index 000000000..056090fbb --- /dev/null +++ b/public/js/simditor.js @@ -0,0 +1,5585 @@ +/*! +* Simditor v2.3.6 +* http://simditor.tower.im/ +* 2015-12-21 +*/ +(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)); + return this.editor.on('blur', (function(_this) { + return function(e) { + return _this.reset(); + }; + })(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.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 = $('').addClass('simditor-caret-start'); + endCaret = $('').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'], + i: ['color'], + strong: ['color'], + strike: ['color'], + u: ['color'], + 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 = $("").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('

' + this.editor.util.phBr + '

'); + 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 = $('
    ').insertBefore(node); + blockNode.append(node); + } + } else { + blockNode = null; + } + } else { + if (!blockNode || blockNode.is('ul, ol')) { + blockNode = $('

    ').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') && $node[0].attributes.length === 0) { + $node.contents().first().unwrap(); + } + } + } else if ($node[0].nodeType === 1 && !$node.is(':empty')) { + if ($node.is('div, article, dl, header, footer, tr')) { + $node.append('
    '); + contents.first().unwrap(); + } else if ($node.is('table')) { + $p = $('

    '); + $node.find('tr').each(function(i, tr) { + return $p.append($(tr).text() + '
    '); + }); + $node.replaceWith($p); + contents = null; + } else if ($node.is('thead, tfoot')) { + $node.remove(); + contents = null; + } else if ($node.is('th')) { + $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 (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 = $('

    ').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) { + $('

    ').append(_this.editor.util.phBr).insertAfter($el); + formatted = true; + } + if ($el.prev().length === 0) { + $('

    ').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.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 = $('

    ').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 = $('
    '); + if (_this.editor.selection.rangeAtEndOf($blockEl)) { + _this.editor.selection.insertNode($br); + _this.editor.selection.insertNode($('
    ')); + _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 = $('

    ').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(); + 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', '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 = $('

  • ').append(_this.editor.util.phBr).insertAfter(listEl.parent('li')); + newListEl = $('<' + listEl[0].tagName + '/>').append($node.nextAll('li')); + newBlockEl.append(newListEl); + } else { + newBlockEl = $('

    ').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 = $('

  • ').insertAfter(listEl.parent('li')); + if ($node.contents().length > 0) { + newBlockEl.append($node.contents()); + } else { + newBlockEl.append(_this.editor.util.phBr); + } + } else { + newBlockEl = $('

    ').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 { + 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 = $('

    ').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'); + range.insertNode(breakNode); + range.setEnd(breakNode, 1); + } else { + breakNode = document.createTextNode('\n'); + range.insertNode(breakNode); + range.setStartAfter(breakNode); + } + 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 = $('

  • ').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', '
    ') || _this.editor.util.phBr; + $newNode = $('

    ').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).parent(); + } + offset = 0; + merging = false; + $parent.contents().each(function(i, child) { + if (node === child || (index === i && i === 0)) { + return false; + } + if (child.nodeType === Node.TEXT_NODE) { + if (!merging && child.nodeValue.length > 0) { + offset += 1; + merging = true; + } + } else { + offset += 1; + merging = false; + } + if (index - 1 === i) { + return false; + } + return null; + }); + return offset; + }; + + UndoManager.prototype._getPosition = function(type) { + var $nodes, node, nodes, offset, position, prevNode, range; + if (type == null) { + type = 'start'; + } + range = this.editor.selection.range(); + offset = range[type + "Offset"]; + $nodes = this.editor.selection[type + "Nodes"](); + node = $nodes.first()[0]; + if (node.nodeType === Node.TEXT_NODE) { + prevNode = node.previousSibling; + while (prevNode && prevNode.nodeType === Node.TEXT_NODE) { + node = prevNode; + offset += this.editor.util.getNodeLength(prevNode); + prevNode = prevNode.previousSibling; + } + nodes = $nodes.get(); + nodes[0] = node; + $nodes = $(nodes); + } else { + offset = this._getNodeOffset(node, offset); + } + position = [offset]; + $nodes.each((function(_this) { + return function(i, node) { + return position.unshift(_this._getNodeOffset(node)); + }; + })(this)); + return position; + }; + + UndoManager.prototype._getNodeByPosition = function(position) { + var child, childNodes, i, k, len, node, offset, ref; + node = this.editor.body[0]; + ref = position.slice(0, position.length - 1); + for (i = k = 0, len = ref.length; k < len; i = ++k) { + offset = ref[i]; + childNodes = node.childNodes; + if (offset > childNodes.length - 1) { + if (i === position.length - 2 && $(node).is('pre:empty')) { + child = document.createTextNode(''); + node.appendChild(child); + childNodes = node.childNodes; + } else { + node = null; + break; + } + } + node = childNodes[offset]; + } + return node; + }; + + UndoManager.prototype.caretPosition = function(caret) { + var endContainer, endOffset, range, startContainer, startOffset; + if (!caret) { + range = this.editor.selection.range(); + caret = this.editor.inputManager.focused && (range != null) ? { + start: this.startPosition(), + end: this.endPosition(), + collapsed: range.collapsed + } : {}; + return caret; + } else { + if (!caret.start) { + return; + } + startContainer = this._getNodeByPosition(caret.start); + startOffset = caret.start[caret.start.length - 1]; + if (caret.collapsed) { + endContainer = startContainer; + endOffset = startOffset; + } else { + endContainer = this._getNodeByPosition(caret.end); + endOffset = caret.start[caret.start.length - 1]; + } + if (!startContainer || !endContainer) { + if (typeof console !== "undefined" && console !== null) { + if (typeof console.warn === "function") { + console.warn('simditor: invalid caret state'); + } + } + return; + } + range = document.createRange(); + range.setStart(startContainer, startOffset); + range.setEnd(endContainer, endOffset); + return this.editor.selection.range(range); + } + }; + + return UndoManager; + +})(SimpleModule); + +Util = (function(superClass) { + extend(Util, superClass); + + function Util() { + return Util.__super__.constructor.apply(this, arguments); + } + + Util.pluginName = 'Util'; + + Util.prototype._init = function() { + this.editor = this._module; + if (this.browser.msie && this.browser.version < 11) { + return this.phBr = ''; + } + }; + + Util.prototype.phBr = '
    '; + + Util.prototype.os = (function() { + var os; + os = {}; + if (/Mac/.test(navigator.appVersion)) { + os.mac = true; + } else if (/Linux/.test(navigator.appVersion)) { + os.linux = true; + } else if (/Win/.test(navigator.appVersion)) { + os.win = true; + } else if (/X11/.test(navigator.appVersion)) { + os.unix = true; + } + if (/Mobi/.test(navigator.appVersion)) { + os.mobile = true; + } + return os; + })(); + + Util.prototype.browser = (function() { + var chrome, edge, firefox, ie, ref, ref1, ref2, ref3, ref4, safari, ua; + ua = navigator.userAgent; + ie = /(msie|trident)/i.test(ua); + chrome = /chrome|crios/i.test(ua); + safari = /safari/i.test(ua) && !chrome; + firefox = /firefox/i.test(ua); + edge = /edge/i.test(ua); + if (ie) { + return { + msie: true, + version: ((ref = ua.match(/(msie |rv:)(\d+(\.\d+)?)/i)) != null ? ref[2] : void 0) * 1 + }; + } else if (edge) { + return { + edge: true, + webkit: true, + version: ((ref1 = ua.match(/edge\/(\d+(\.\d+)?)/i)) != null ? ref1[1] : void 0) * 1 + }; + } else if (chrome) { + return { + webkit: true, + chrome: true, + version: ((ref2 = ua.match(/(?:chrome|crios)\/(\d+(\.\d+)?)/i)) != null ? ref2[1] : void 0) * 1 + }; + } else if (safari) { + return { + webkit: true, + safari: true, + version: ((ref3 = ua.match(/version\/(\d+(\.\d+)?)/i)) != null ? ref3[1] : void 0) * 1 + }; + } else if (firefox) { + return { + mozilla: true, + firefox: true, + version: ((ref4 = ua.match(/firefox\/(\d+(\.\d+)?)/i)) != null ? ref4[1] : void 0) * 1 + }; + } else { + return {}; + } + })(); + + Util.prototype.support = (function() { + return { + onselectionchange: (function() { + var e, onselectionchange; + onselectionchange = document.onselectionchange; + if (onselectionchange !== void 0) { + try { + document.onselectionchange = 0; + return document.onselectionchange === null; + } catch (_error) { + e = _error; + } finally { + document.onselectionchange = onselectionchange; + } + } + return false; + })(), + oninput: (function() { + return !/(msie|trident)/i.test(navigator.userAgent); + })() + }; + })(); + + Util.prototype.reflow = function(el) { + if (el == null) { + el = document; + } + return $(el)[0].offsetHeight; + }; + + Util.prototype.metaKey = function(e) { + var isMac; + isMac = /Mac/.test(navigator.userAgent); + if (isMac) { + return e.metaKey; + } else { + return e.ctrlKey; + } + }; + + Util.prototype.isEmptyNode = function(node) { + var $node; + $node = $(node); + return $node.is(':empty') || (!$node.text() && !$node.find(':not(br, span, div)').length); + }; + + Util.prototype.isDecoratedNode = function(node) { + return $(node).is('[class^="simditor-"]'); + }; + + Util.prototype.blockNodes = ["div", "p", "ul", "ol", "li", "blockquote", "hr", "pre", "h1", "h2", "h3", "h4", "h5", "table"]; + + Util.prototype.isBlockNode = function(node) { + node = $(node)[0]; + if (!node || node.nodeType === 3) { + return false; + } + return new RegExp("^(" + (this.blockNodes.join('|')) + ")$").test(node.nodeName.toLowerCase()); + }; + + Util.prototype.getNodeLength = function(node) { + node = $(node)[0]; + switch (node.nodeType) { + case 7: + case 10: + return 0; + case 3: + case 8: + return node.length; + default: + return node.childNodes.length; + } + }; + + Util.prototype.dataURLtoBlob = function(dataURL) { + var BlobBuilder, arrayBuffer, bb, blobArray, byteString, hasArrayBufferViewSupport, hasBlobConstructor, i, intArray, k, mimeString, ref, supportBlob; + hasBlobConstructor = window.Blob && (function() { + var e; + try { + return Boolean(new Blob()); + } catch (_error) { + e = _error; + return false; + } + })(); + hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && (function() { + var e; + try { + return new Blob([new Uint8Array(100)]).size === 100; + } catch (_error) { + e = _error; + return false; + } + })(); + BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; + supportBlob = hasBlobConstructor || BlobBuilder; + if (!(supportBlob && window.atob && window.ArrayBuffer && window.Uint8Array)) { + return false; + } + if (dataURL.split(',')[0].indexOf('base64') >= 0) { + byteString = atob(dataURL.split(',')[1]); + } else { + byteString = decodeURIComponent(dataURL.split(',')[1]); + } + arrayBuffer = new ArrayBuffer(byteString.length); + intArray = new Uint8Array(arrayBuffer); + for (i = k = 0, ref = byteString.length; 0 <= ref ? k <= ref : k >= ref; i = 0 <= ref ? ++k : --k) { + intArray[i] = byteString.charCodeAt(i); + } + mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]; + if (hasBlobConstructor) { + blobArray = hasArrayBufferViewSupport ? intArray : arrayBuffer; + return new Blob([blobArray], { + type: mimeString + }); + } + bb = new BlobBuilder(); + bb.append(arrayBuffer); + return bb.getBlob(mimeString); + }; + + Util.prototype.throttle = function(func, wait) { + var args, call, ctx, last, rtn, throttled, timeoutID; + last = 0; + timeoutID = 0; + ctx = args = rtn = null; + call = function() { + timeoutID = 0; + last = +new Date(); + rtn = func.apply(ctx, args); + ctx = null; + return args = null; + }; + throttled = function() { + var delta; + ctx = this; + args = arguments; + delta = new Date() - last; + if (!timeoutID) { + if (delta >= wait) { + call(); + } else { + timeoutID = setTimeout(call, wait - delta); + } + } + return rtn; + }; + throttled.clear = function() { + if (!timeoutID) { + return; + } + clearTimeout(timeoutID); + return call(); + }; + return throttled; + }; + + Util.prototype.formatHTML = function(html) { + var cursor, indentString, lastMatch, level, match, re, repeatString, result, str; + re = /<(\/?)(.+?)(\/?)>/g; + result = ''; + level = 0; + lastMatch = null; + indentString = ' '; + repeatString = function(str, n) { + return new Array(n + 1).join(str); + }; + while ((match = re.exec(html)) !== null) { + match.isBlockNode = $.inArray(match[2], this.blockNodes) > -1; + match.isStartTag = match[1] !== '/' && match[3] !== '/'; + match.isEndTag = match[1] === '/' || match[3] === '/'; + cursor = lastMatch ? lastMatch.index + lastMatch[0].length : 0; + if ((str = html.substring(cursor, match.index)).length > 0 && $.trim(str)) { + result += str; + } + if (match.isBlockNode && match.isEndTag && !match.isStartTag) { + level -= 1; + } + if (match.isBlockNode && match.isStartTag) { + if (!(lastMatch && lastMatch.isBlockNode && lastMatch.isEndTag)) { + result += '\n'; + } + result += repeatString(indentString, level); + } + result += match[0]; + if (match.isBlockNode && match.isEndTag) { + result += '\n'; + } + if (match.isBlockNode && match.isStartTag) { + level += 1; + } + lastMatch = match; + } + return $.trim(result); + }; + + return Util; + +})(SimpleModule); + +Toolbar = (function(superClass) { + extend(Toolbar, superClass); + + function Toolbar() { + return Toolbar.__super__.constructor.apply(this, arguments); + } + + Toolbar.pluginName = 'Toolbar'; + + Toolbar.prototype.opts = { + toolbar: true, + toolbarFloat: true, + toolbarHidden: false, + toolbarFloatOffset: 0 + }; + + Toolbar.prototype._tpl = { + wrapper: '

      ', + separator: '
    • ' + }; + + Toolbar.prototype._init = function() { + var floatInitialized, initToolbarFloat, toolbarHeight; + this.editor = this._module; + if (!this.opts.toolbar) { + return; + } + if (!$.isArray(this.opts.toolbar)) { + this.opts.toolbar = ['bold', 'italic', 'underline', 'strikethrough', '|', 'ol', 'ul', 'blockquote', 'code', '|', 'link', 'image', '|', 'indent', 'outdent']; + } + this._render(); + this.list.on('click', function(e) { + return false; + }); + this.wrapper.on('mousedown', (function(_this) { + return function(e) { + return _this.list.find('.menu-on').removeClass('.menu-on'); + }; + })(this)); + $(document).on('mousedown.simditor' + this.editor.id, (function(_this) { + return function(e) { + return _this.list.find('.menu-on').removeClass('.menu-on'); + }; + })(this)); + if (!this.opts.toolbarHidden && this.opts.toolbarFloat) { + this.wrapper.css('top', this.opts.toolbarFloatOffset); + toolbarHeight = 0; + initToolbarFloat = (function(_this) { + return function() { + _this.wrapper.css('position', 'static'); + _this.wrapper.width('auto'); + _this.editor.util.reflow(_this.wrapper); + _this.wrapper.width(_this.wrapper.outerWidth()); + _this.wrapper.css('left', _this.editor.util.os.mobile ? _this.wrapper.position().left : _this.wrapper.offset().left); + _this.wrapper.css('position', ''); + toolbarHeight = _this.wrapper.outerHeight(); + _this.editor.placeholderEl.css('top', toolbarHeight); + return true; + }; + })(this); + floatInitialized = null; + $(window).on('resize.simditor-' + this.editor.id, function(e) { + return floatInitialized = initToolbarFloat(); + }); + $(window).on('scroll.simditor-' + this.editor.id, (function(_this) { + return function(e) { + var bottomEdge, scrollTop, topEdge; + if (!_this.wrapper.is(':visible')) { + return; + } + topEdge = _this.editor.wrapper.offset().top; + bottomEdge = topEdge + _this.editor.wrapper.outerHeight() - 80; + scrollTop = $(document).scrollTop() + _this.opts.toolbarFloatOffset; + if (scrollTop <= topEdge || scrollTop >= bottomEdge) { + _this.editor.wrapper.removeClass('toolbar-floating').css('padding-top', ''); + if (_this.editor.util.os.mobile) { + return _this.wrapper.css('top', _this.opts.toolbarFloatOffset); + } + } else { + floatInitialized || (floatInitialized = initToolbarFloat()); + _this.editor.wrapper.addClass('toolbar-floating').css('padding-top', toolbarHeight); + if (_this.editor.util.os.mobile) { + return _this.wrapper.css('top', scrollTop - topEdge + _this.opts.toolbarFloatOffset); + } + } + }; + })(this)); + } + this.editor.on('destroy', (function(_this) { + return function() { + return _this.buttons.length = 0; + }; + })(this)); + return $(document).on("mousedown.simditor-" + this.editor.id, (function(_this) { + return function(e) { + return _this.list.find('li.menu-on').removeClass('menu-on'); + }; + })(this)); + }; + + Toolbar.prototype._render = function() { + var k, len, name, ref; + this.buttons = []; + this.wrapper = $(this._tpl.wrapper).prependTo(this.editor.wrapper); + this.list = this.wrapper.find('ul'); + ref = this.opts.toolbar; + for (k = 0, len = ref.length; k < len; k++) { + name = ref[k]; + if (name === '|') { + $(this._tpl.separator).appendTo(this.list); + continue; + } + if (!this.constructor.buttons[name]) { + throw new Error("simditor: invalid toolbar button " + name); + continue; + } + this.buttons.push(new this.constructor.buttons[name]({ + editor: this.editor + })); + } + if (this.opts.toolbarHidden) { + return this.wrapper.hide(); + } + }; + + Toolbar.prototype.findButton = function(name) { + var button; + button = this.list.find('.toolbar-item-' + name).data('button'); + return button != null ? button : null; + }; + + Toolbar.addButton = function(btn) { + return this.buttons[btn.prototype.name] = btn; + }; + + Toolbar.buttons = {}; + + return Toolbar; + +})(SimpleModule); + +Indentation = (function(superClass) { + extend(Indentation, superClass); + + function Indentation() { + return Indentation.__super__.constructor.apply(this, arguments); + } + + Indentation.pluginName = 'Indentation'; + + Indentation.prototype.opts = { + tabIndent: true + }; + + Indentation.prototype._init = function() { + this.editor = this._module; + return this.editor.keystroke.add('tab', '*', (function(_this) { + return function(e) { + var codeButton; + codeButton = _this.editor.toolbar.findButton('code'); + if (!(_this.opts.tabIndent || (codeButton && codeButton.active))) { + return; + } + return _this.indent(e.shiftKey); + }; + })(this)); + }; + + Indentation.prototype.indent = function(isBackward) { + var $blockNodes, $endNodes, $startNodes, nodes, result; + $startNodes = this.editor.selection.startNodes(); + $endNodes = this.editor.selection.endNodes(); + $blockNodes = this.editor.selection.blockNodes(); + nodes = []; + $blockNodes = $blockNodes.each(function(i, node) { + var include, j, k, len, n; + include = true; + for (j = k = 0, len = nodes.length; k < len; j = ++k) { + n = nodes[j]; + if ($.contains(node, n)) { + include = false; + break; + } else if ($.contains(n, node)) { + nodes.splice(j, 1, node); + include = false; + break; + } + } + if (include) { + return nodes.push(node); + } + }); + $blockNodes = $(nodes); + result = false; + $blockNodes.each((function(_this) { + return function(i, blockEl) { + var r; + r = isBackward ? _this.outdentBlock(blockEl) : _this.indentBlock(blockEl); + if (r) { + return result = r; + } + }; + })(this)); + return result; + }; + + Indentation.prototype.indentBlock = function(blockEl) { + var $blockEl, $childList, $nextTd, $nextTr, $parentLi, $pre, $td, $tr, marginLeft, tagName; + $blockEl = $(blockEl); + if (!$blockEl.length) { + return; + } + if ($blockEl.is('pre')) { + $pre = this.editor.selection.containerNode(); + if (!($pre.is($blockEl) || $pre.closest('pre').is($blockEl))) { + return; + } + this.indentText(this.editor.selection.range()); + } else if ($blockEl.is('li')) { + $parentLi = $blockEl.prev('li'); + if ($parentLi.length < 1) { + return; + } + this.editor.selection.save(); + tagName = $blockEl.parent()[0].tagName; + $childList = $parentLi.children('ul, ol'); + if ($childList.length > 0) { + $childList.append($blockEl); + } else { + $('<' + tagName + '/>').append($blockEl).appendTo($parentLi); + } + this.editor.selection.restore(); + } else if ($blockEl.is('p, h1, h2, h3, h4')) { + marginLeft = parseInt($blockEl.css('margin-left')) || 0; + marginLeft = (Math.round(marginLeft / this.opts.indentWidth) + 1) * this.opts.indentWidth; + $blockEl.css('margin-left', marginLeft); + } else if ($blockEl.is('table') || $blockEl.is('.simditor-table')) { + $td = this.editor.selection.containerNode().closest('td, th'); + $nextTd = $td.next('td, th'); + if (!($nextTd.length > 0)) { + $tr = $td.parent('tr'); + $nextTr = $tr.next('tr'); + if ($nextTr.length < 1 && $tr.parent().is('thead')) { + $nextTr = $tr.parent('thead').next('tbody').find('tr:first'); + } + $nextTd = $nextTr.find('td:first, th:first'); + } + if (!($td.length > 0 && $nextTd.length > 0)) { + return; + } + this.editor.selection.setRangeAtEndOf($nextTd); + } else { + return false; + } + return true; + }; + + Indentation.prototype.indentText = function(range) { + var text, textNode; + text = range.toString().replace(/^(?=.+)/mg, '\u00A0\u00A0'); + textNode = document.createTextNode(text || '\u00A0\u00A0'); + range.deleteContents(); + range.insertNode(textNode); + if (text) { + range.selectNode(textNode); + return this.editor.selection.range(range); + } else { + return this.editor.selection.setRangeAfter(textNode); + } + }; + + Indentation.prototype.outdentBlock = function(blockEl) { + var $blockEl, $parent, $parentLi, $pre, $prevTd, $prevTr, $td, $tr, marginLeft, range; + $blockEl = $(blockEl); + if (!($blockEl && $blockEl.length > 0)) { + return; + } + if ($blockEl.is('pre')) { + $pre = this.editor.selection.containerNode(); + if (!($pre.is($blockEl) || $pre.closest('pre').is($blockEl))) { + return; + } + this.outdentText(range); + } else if ($blockEl.is('li')) { + $parent = $blockEl.parent(); + $parentLi = $parent.parent('li'); + this.editor.selection.save(); + if ($parentLi.length < 1) { + range = document.createRange(); + range.setStartBefore($parent[0]); + range.setEndBefore($blockEl[0]); + $parent.before(range.extractContents()); + $('

      ').insertBefore($parent).after($blockEl.children('ul, ol')).append($blockEl.contents()); + $blockEl.remove(); + } else { + if ($blockEl.next('li').length > 0) { + $('<' + $parent[0].tagName + '/>').append($blockEl.nextAll('li')).appendTo($blockEl); + } + $blockEl.insertAfter($parentLi); + if ($parent.children('li').length < 1) { + $parent.remove(); + } + } + this.editor.selection.restore(); + } else if ($blockEl.is('p, h1, h2, h3, h4')) { + marginLeft = parseInt($blockEl.css('margin-left')) || 0; + marginLeft = Math.max(Math.round(marginLeft / this.opts.indentWidth) - 1, 0) * this.opts.indentWidth; + $blockEl.css('margin-left', marginLeft === 0 ? '' : marginLeft); + } else if ($blockEl.is('table') || $blockEl.is('.simditor-table')) { + $td = this.editor.selection.containerNode().closest('td, th'); + $prevTd = $td.prev('td, th'); + if (!($prevTd.length > 0)) { + $tr = $td.parent('tr'); + $prevTr = $tr.prev('tr'); + if ($prevTr.length < 1 && $tr.parent().is('tbody')) { + $prevTr = $tr.parent('tbody').prev('thead').find('tr:first'); + } + $prevTd = $prevTr.find('td:last, th:last'); + } + if (!($td.length > 0 && $prevTd.length > 0)) { + return; + } + this.editor.selection.setRangeAtEndOf($prevTd); + } else { + return false; + } + return true; + }; + + Indentation.prototype.outdentText = function(range) {}; + + return Indentation; + +})(SimpleModule); + +Clipboard = (function(superClass) { + extend(Clipboard, superClass); + + function Clipboard() { + return Clipboard.__super__.constructor.apply(this, arguments); + } + + Clipboard.pluginName = 'Clipboard'; + + Clipboard.prototype.opts = { + pasteImage: false, + cleanPaste: false + }; + + Clipboard.prototype._init = function() { + this.editor = this._module; + if (this.opts.pasteImage && typeof this.opts.pasteImage !== 'string') { + this.opts.pasteImage = 'inline'; + } + return this.editor.body.on('paste', (function(_this) { + return function(e) { + var range; + if (_this.pasting || _this._pasteBin) { + return; + } + if (_this.editor.triggerHandler(e) === false) { + return false; + } + range = _this.editor.selection.deleteRangeContents(); + if (_this.editor.body.html()) { + if (!range.collapsed) { + range.collapse(true); + } + } else { + _this.editor.formatter.format(); + _this.editor.selection.setRangeAtStartOf(_this.editor.body.find('p:first')); + } + if (_this._processPasteByClipboardApi(e)) { + return false; + } + _this.editor.inputManager.throttledValueChanged.clear(); + _this.editor.inputManager.throttledSelectionChanged.clear(); + _this.editor.undoManager.throttledPushState.clear(); + _this.editor.selection.reset(); + _this.editor.undoManager.resetCaretPosition(); + _this.pasting = true; + return _this._getPasteContent(function(pasteContent) { + _this._processPasteContent(pasteContent); + _this._pasteInBlockEl = null; + _this._pastePlainText = null; + return _this.pasting = false; + }); + }; + })(this)); + }; + + Clipboard.prototype._processPasteByClipboardApi = function(e) { + var imageFile, pasteItem, ref, uploadOpt; + if (this.editor.util.browser.edge) { + return; + } + if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.items && e.originalEvent.clipboardData.items.length > 0) { + pasteItem = e.originalEvent.clipboardData.items[0]; + if (/^image\//.test(pasteItem.type)) { + imageFile = pasteItem.getAsFile(); + if (!((imageFile != null) && this.opts.pasteImage)) { + return; + } + if (!imageFile.name) { + imageFile.name = "Clipboard Image.png"; + } + if (this.editor.triggerHandler('pasting', [imageFile]) === false) { + return; + } + uploadOpt = {}; + uploadOpt[this.opts.pasteImage] = true; + if ((ref = this.editor.uploader) != null) { + ref.upload(imageFile, uploadOpt); + } + return true; + } + } + }; + + Clipboard.prototype._getPasteContent = function(callback) { + var state; + this._pasteBin = $('

      ').addClass('simditor-paste-bin').attr('tabIndex', '-1').appendTo(this.editor.el); + state = { + html: this.editor.body.html(), + caret: this.editor.undoManager.caretPosition() + }; + this._pasteBin.focus(); + return setTimeout((function(_this) { + return function() { + var pasteContent; + _this.editor.hidePopover(); + _this.editor.body.get(0).innerHTML = state.html; + _this.editor.undoManager.caretPosition(state.caret); + _this.editor.body.focus(); + _this.editor.selection.reset(); + _this.editor.selection.range(); + _this._pasteInBlockEl = _this.editor.selection.blockNodes().last(); + _this._pastePlainText = _this.opts.cleanPaste || _this._pasteInBlockEl.is('pre, table'); + if (_this._pastePlainText) { + pasteContent = _this.editor.formatter.clearHtml(_this._pasteBin.html(), true); + } else { + pasteContent = $('
      ').append(_this._pasteBin.contents()); + pasteContent.find('table colgroup').remove(); + _this.editor.formatter.format(pasteContent); + _this.editor.formatter.decorate(pasteContent); + _this.editor.formatter.beautify(pasteContent.children()); + pasteContent = pasteContent.contents(); + } + _this._pasteBin.remove(); + _this._pasteBin = null; + return callback(pasteContent); + }; + })(this), 0); + }; + + Clipboard.prototype._processPasteContent = function(pasteContent) { + var $blockEl, $img, blob, children, insertPosition, k, l, lastLine, len, len1, len2, len3, len4, line, lines, m, node, o, q, ref, ref1, ref2, uploadOpt; + if (this.editor.triggerHandler('pasting', [pasteContent]) === false) { + return; + } + $blockEl = this._pasteInBlockEl; + if (!pasteContent) { + return; + } else if (this._pastePlainText) { + if ($blockEl.is('table')) { + lines = pasteContent.split('\n'); + lastLine = lines.pop(); + for (k = 0, len = lines.length; k < len; k++) { + line = lines[k]; + this.editor.selection.insertNode(document.createTextNode(line)); + this.editor.selection.insertNode($('
      ')); + } + this.editor.selection.insertNode(document.createTextNode(lastLine)); + } else { + pasteContent = $('
      ').text(pasteContent); + ref = pasteContent.contents(); + for (l = 0, len1 = ref.length; l < len1; l++) { + node = ref[l]; + this.editor.selection.insertNode($(node)[0]); + } + } + } else if ($blockEl.is(this.editor.body)) { + for (m = 0, len2 = pasteContent.length; m < len2; m++) { + node = pasteContent[m]; + this.editor.selection.insertNode(node); + } + } else if (pasteContent.length < 1) { + return; + } else if (pasteContent.length === 1) { + if (pasteContent.is('p')) { + children = pasteContent.contents(); + if (children.length === 1 && children.is('img')) { + $img = children; + if (/^data:image/.test($img.attr('src'))) { + if (!this.opts.pasteImage) { + return; + } + blob = this.editor.util.dataURLtoBlob($img.attr("src")); + blob.name = "Clipboard Image.png"; + uploadOpt = {}; + uploadOpt[this.opts.pasteImage] = true; + if ((ref1 = this.editor.uploader) != null) { + ref1.upload(blob, uploadOpt); + } + return; + } else if ($img.is('img[src^="webkit-fake-url://"]')) { + return; + } + } + for (o = 0, len3 = children.length; o < len3; o++) { + node = children[o]; + this.editor.selection.insertNode(node); + } + } else if ($blockEl.is('p') && this.editor.util.isEmptyNode($blockEl)) { + $blockEl.replaceWith(pasteContent); + this.editor.selection.setRangeAtEndOf(pasteContent); + } else if (pasteContent.is('ul, ol')) { + if (pasteContent.find('li').length === 1) { + pasteContent = $('
      ').text(pasteContent.text()); + ref2 = pasteContent.contents(); + for (q = 0, len4 = ref2.length; q < len4; q++) { + node = ref2[q]; + this.editor.selection.insertNode($(node)[0]); + } + } else if ($blockEl.is('li')) { + $blockEl.parent().after(pasteContent); + this.editor.selection.setRangeAtEndOf(pasteContent); + } else { + $blockEl.after(pasteContent); + this.editor.selection.setRangeAtEndOf(pasteContent); + } + } else { + $blockEl.after(pasteContent); + this.editor.selection.setRangeAtEndOf(pasteContent); + } + } else { + if ($blockEl.is('li')) { + $blockEl = $blockEl.parent(); + } + if (this.editor.selection.rangeAtStartOf($blockEl)) { + insertPosition = 'before'; + } else if (this.editor.selection.rangeAtEndOf($blockEl)) { + insertPosition = 'after'; + } else { + this.editor.selection.breakBlockEl($blockEl); + insertPosition = 'before'; + } + $blockEl[insertPosition](pasteContent); + this.editor.selection.setRangeAtEndOf(pasteContent.last()); + } + return this.editor.inputManager.throttledValueChanged(); + }; + + return Clipboard; + +})(SimpleModule); + +Simditor = (function(superClass) { + extend(Simditor, superClass); + + function Simditor() { + return Simditor.__super__.constructor.apply(this, arguments); + } + + Simditor.connect(Util); + + Simditor.connect(InputManager); + + Simditor.connect(Selection); + + Simditor.connect(UndoManager); + + Simditor.connect(Keystroke); + + Simditor.connect(Formatter); + + Simditor.connect(Toolbar); + + Simditor.connect(Indentation); + + Simditor.connect(Clipboard); + + Simditor.count = 0; + + Simditor.prototype.opts = { + textarea: null, + placeholder: '', + defaultImage: 'images/image.png', + params: {}, + upload: false, + indentWidth: 40 + }; + + Simditor.prototype._init = function() { + var e, editor, form, uploadOpts; + this.textarea = $(this.opts.textarea); + this.opts.placeholder = this.opts.placeholder || this.textarea.attr('placeholder'); + if (!this.textarea.length) { + throw new Error('simditor: param textarea is required.'); + return; + } + editor = this.textarea.data('simditor'); + if (editor != null) { + editor.destroy(); + } + this.id = ++Simditor.count; + this._render(); + if (simpleHotkeys) { + this.hotkeys = simpleHotkeys({ + el: this.body + }); + } else { + throw new Error('simditor: simple-hotkeys is required.'); + return; + } + if (this.opts.upload && simpleUploader) { + uploadOpts = typeof this.opts.upload === 'object' ? this.opts.upload : {}; + this.uploader = simpleUploader(uploadOpts); + } + form = this.textarea.closest('form'); + if (form.length) { + form.on('submit.simditor-' + this.id, (function(_this) { + return function() { + return _this.sync(); + }; + })(this)); + form.on('reset.simditor-' + this.id, (function(_this) { + return function() { + return _this.setValue(''); + }; + })(this)); + } + this.on('initialized', (function(_this) { + return function() { + if (_this.opts.placeholder) { + _this.on('valuechanged', function() { + return _this._placeholder(); + }); + } + _this.setValue(_this.textarea.val().trim() || ''); + if (_this.textarea.attr('autofocus')) { + return _this.focus(); + } + }; + })(this)); + if (this.util.browser.mozilla) { + this.util.reflow(); + try { + document.execCommand('enableObjectResizing', false, false); + return document.execCommand('enableInlineTableEditing', false, false); + } catch (_error) { + e = _error; + } + } + }; + + Simditor.prototype._tpl = "
      \n
      \n
      \n
      \n
      \n
      \n
      "; + + Simditor.prototype._render = function() { + var key, ref, results, val; + this.el = $(this._tpl).insertBefore(this.textarea); + this.wrapper = this.el.find('.simditor-wrapper'); + this.body = this.wrapper.find('.simditor-body'); + this.placeholderEl = this.wrapper.find('.simditor-placeholder').append(this.opts.placeholder); + this.el.data('simditor', this); + this.wrapper.append(this.textarea); + this.textarea.data('simditor', this).blur(); + this.body.attr('tabindex', this.textarea.attr('tabindex')); + if (this.util.os.mac) { + this.el.addClass('simditor-mac'); + } else if (this.util.os.linux) { + this.el.addClass('simditor-linux'); + } + if (this.util.os.mobile) { + this.el.addClass('simditor-mobile'); + } + if (this.opts.params) { + ref = this.opts.params; + results = []; + for (key in ref) { + val = ref[key]; + results.push($('', { + type: 'hidden', + name: key, + value: val + }).insertAfter(this.textarea)); + } + return results; + } + }; + + Simditor.prototype._placeholder = function() { + var children; + children = this.body.children(); + if (children.length === 0 || (children.length === 1 && this.util.isEmptyNode(children) && parseInt(children.css('margin-left') || 0) < this.opts.indentWidth)) { + return this.placeholderEl.show(); + } else { + return this.placeholderEl.hide(); + } + }; + + Simditor.prototype.setValue = function(val) { + this.hidePopover(); + this.textarea.val(val); + this.body.get(0).innerHTML = val; + this.formatter.format(); + this.formatter.decorate(); + this.util.reflow(this.body); + this.inputManager.lastCaretPosition = null; + return this.trigger('valuechanged'); + }; + + Simditor.prototype.getValue = function() { + return this.sync(); + }; + + Simditor.prototype.sync = function() { + var children, cloneBody, emptyP, firstP, lastP, val; + cloneBody = this.body.clone(); + this.formatter.undecorate(cloneBody); + this.formatter.format(cloneBody); + this.formatter.autolink(cloneBody); + children = cloneBody.children(); + lastP = children.last('p'); + firstP = children.first('p'); + while (lastP.is('p') && this.util.isEmptyNode(lastP)) { + emptyP = lastP; + lastP = lastP.prev('p'); + emptyP.remove(); + } + while (firstP.is('p') && this.util.isEmptyNode(firstP)) { + emptyP = firstP; + firstP = lastP.next('p'); + emptyP.remove(); + } + cloneBody.find('img.uploading').remove(); + val = $.trim(cloneBody.html()); + this.textarea.val(val); + return val; + }; + + Simditor.prototype.focus = function() { + var $blockEl, range; + if (!(this.body.is(':visible') && this.body.is('[contenteditable]'))) { + this.el.find('textarea:visible').focus(); + return; + } + if (this.inputManager.lastCaretPosition) { + this.undoManager.caretPosition(this.inputManager.lastCaretPosition); + return this.inputManager.lastCaretPosition = null; + } else { + $blockEl = this.body.children().last(); + if (!$blockEl.is('p')) { + $blockEl = $('

      ').append(this.util.phBr).appendTo(this.body); + } + range = document.createRange(); + return this.selection.setRangeAtEndOf($blockEl, range); + } + }; + + Simditor.prototype.blur = function() { + if (this.body.is(':visible') && this.body.is('[contenteditable]')) { + return this.body.blur(); + } else { + return this.body.find('textarea:visible').blur(); + } + }; + + Simditor.prototype.hidePopover = function() { + return this.el.find('.simditor-popover').each(function(i, popover) { + popover = $(popover).data('popover'); + if (popover.active) { + return popover.hide(); + } + }); + }; + + Simditor.prototype.destroy = function() { + this.triggerHandler('destroy'); + this.textarea.closest('form').off('.simditor .simditor-' + this.id); + this.selection.clear(); + this.inputManager.focused = false; + this.textarea.insertBefore(this.el).hide().val('').removeData('simditor'); + this.el.remove(); + $(document).off('.simditor-' + this.id); + $(window).off('.simditor-' + this.id); + return this.off(); + }; + + return Simditor; + +})(SimpleModule); + +Simditor.i18n = { + 'zh-CN': { + 'blockquote': '引用', + 'bold': '加粗文字', + 'code': '插入代码', + 'color': '文字颜色', + 'coloredText': '彩色文字', + 'hr': '分隔线', + 'image': '插入图片', + 'externalImage': '外链图片', + 'uploadImage': '上传图片', + 'uploadFailed': '上传失败了', + 'uploadError': '上传出错了', + 'imageUrl': '图片地址', + 'imageSize': '图片尺寸', + 'imageAlt': '图片描述', + 'restoreImageSize': '还原图片尺寸', + 'uploading': '正在上传', + 'indent': '向右缩进', + 'outdent': '向左缩进', + 'italic': '斜体文字', + 'link': '插入链接', + 'linkText': '链接文字', + 'linkUrl': '链接地址', + 'linkTarget': '打开方式', + 'openLinkInCurrentWindow': '在新窗口中打开', + 'openLinkInNewWindow': '在当前窗口中打开', + 'removeLink': '移除链接', + 'ol': '有序列表', + 'ul': '无序列表', + 'strikethrough': '删除线文字', + 'table': '表格', + 'deleteRow': '删除行', + 'insertRowAbove': '在上面插入行', + 'insertRowBelow': '在下面插入行', + 'deleteColumn': '删除列', + 'insertColumnLeft': '在左边插入列', + 'insertColumnRight': '在右边插入列', + 'deleteTable': '删除表格', + 'title': '标题', + 'normalText': '普通文本', + 'underline': '下划线文字', + 'alignment': '水平对齐', + 'alignCenter': '居中', + 'alignLeft': '居左', + 'alignRight': '居右', + 'selectLanguage': '选择程序语言', + 'fontScale': '字体大小', + 'fontScaleXLarge': '超大字体', + 'fontScaleLarge': '大号字体', + 'fontScaleNormal': '正常大小', + 'fontScaleSmall': '小号字体', + 'fontScaleXSmall': '超小字体' + }, + 'en-US': { + 'blockquote': 'Block Quote', + 'bold': 'Bold', + 'code': 'Code', + 'color': 'Text Color', + 'coloredText': 'Colored Text', + 'hr': 'Horizontal Line', + 'image': 'Insert Image', + 'externalImage': 'External Image', + 'uploadImage': 'Upload Image', + 'uploadFailed': 'Upload failed', + 'uploadError': 'Error occurs during upload', + 'imageUrl': 'Url', + 'imageSize': 'Size', + 'imageAlt': 'Alt', + 'restoreImageSize': 'Restore Origin Size', + 'uploading': 'Uploading', + 'indent': 'Indent', + 'outdent': 'Outdent', + 'italic': 'Italic', + 'link': 'Insert Link', + 'linkText': 'Text', + 'linkUrl': 'Url', + 'linkTarget': 'Target', + 'openLinkInCurrentWindow': 'Open link in current window', + 'openLinkInNewWindow': 'Open link in new window', + 'removeLink': 'Remove Link', + 'ol': 'Ordered List', + 'ul': 'Unordered List', + 'strikethrough': 'Strikethrough', + 'table': 'Table', + 'deleteRow': 'Delete Row', + 'insertRowAbove': 'Insert Row Above', + 'insertRowBelow': 'Insert Row Below', + 'deleteColumn': 'Delete Column', + 'insertColumnLeft': 'Insert Column Left', + 'insertColumnRight': 'Insert Column Right', + 'deleteTable': 'Delete Table', + 'title': 'Title', + 'normalText': 'Text', + 'underline': 'Underline', + 'alignment': 'Alignment', + 'alignCenter': 'Align Center', + 'alignLeft': 'Align Left', + 'alignRight': 'Align Right', + 'selectLanguage': 'Select Language', + 'fontScale': 'Font Size', + 'fontScaleXLarge': 'X Large Size', + 'fontScaleLarge': 'Large Size', + 'fontScaleNormal': 'Normal Size', + 'fontScaleSmall': 'Small Size', + 'fontScaleXSmall': 'X Small Size' + } +}; + +Button = (function(superClass) { + extend(Button, superClass); + + Button.prototype._tpl = { + item: '

    • ', + menuWrapper: '
      ', + menuItem: '
    • ', + separator: '
    • ' + }; + + Button.prototype.name = ''; + + Button.prototype.icon = ''; + + Button.prototype.title = ''; + + Button.prototype.text = ''; + + Button.prototype.htmlTag = ''; + + Button.prototype.disableTag = ''; + + Button.prototype.menu = false; + + Button.prototype.active = false; + + Button.prototype.disabled = false; + + Button.prototype.needFocus = true; + + Button.prototype.shortcut = null; + + function Button(opts) { + this.editor = opts.editor; + this.title = this._t(this.name); + Button.__super__.constructor.call(this, opts); + } + + Button.prototype._init = function() { + var k, len, ref, tag; + this.render(); + this.el.on('mousedown', (function(_this) { + return function(e) { + var exceed, noFocus, param; + e.preventDefault(); + noFocus = _this.needFocus && !_this.editor.inputManager.focused; + if (_this.el.hasClass('disabled') || noFocus) { + return false; + } + if (_this.menu) { + _this.wrapper.toggleClass('menu-on').siblings('li').removeClass('menu-on'); + if (_this.wrapper.is('.menu-on')) { + exceed = _this.menuWrapper.offset().left + _this.menuWrapper.outerWidth() + 5 - _this.editor.wrapper.offset().left - _this.editor.wrapper.outerWidth(); + if (exceed > 0) { + _this.menuWrapper.css({ + 'left': 'auto', + 'right': 0 + }); + } + _this.trigger('menuexpand'); + } + return false; + } + param = _this.el.data('param'); + _this.command(param); + return false; + }; + })(this)); + this.wrapper.on('click', 'a.menu-item', (function(_this) { + return function(e) { + var btn, noFocus, param; + e.preventDefault(); + btn = $(e.currentTarget); + _this.wrapper.removeClass('menu-on'); + noFocus = _this.needFocus && !_this.editor.inputManager.focused; + if (btn.hasClass('disabled') || noFocus) { + return false; + } + _this.editor.toolbar.wrapper.removeClass('menu-on'); + param = btn.data('param'); + _this.command(param); + return false; + }; + })(this)); + this.wrapper.on('mousedown', 'a.menu-item', function(e) { + return false; + }); + this.editor.on('blur', (function(_this) { + return function() { + var editorActive; + editorActive = _this.editor.body.is(':visible') && _this.editor.body.is('[contenteditable]'); + if (!(editorActive && !_this.editor.clipboard.pasting)) { + return; + } + _this.setActive(false); + return _this.setDisabled(false); + }; + })(this)); + if (this.shortcut != null) { + this.editor.hotkeys.add(this.shortcut, (function(_this) { + return function(e) { + _this.el.mousedown(); + return false; + }; + })(this)); + } + ref = this.htmlTag.split(','); + for (k = 0, len = ref.length; k < len; k++) { + tag = ref[k]; + tag = $.trim(tag); + if (tag && $.inArray(tag, this.editor.formatter._allowedTags) < 0) { + this.editor.formatter._allowedTags.push(tag); + } + } + return this.editor.on('selectionchanged', (function(_this) { + return function(e) { + if (_this.editor.inputManager.focused) { + return _this._status(); + } + }; + })(this)); + }; + + Button.prototype.iconClassOf = function(icon) { + if (icon) { + return "simditor-icon simditor-icon-" + icon; + } else { + return ''; + } + }; + + Button.prototype.setIcon = function(icon) { + return this.el.find('span').removeClass().addClass(this.iconClassOf(icon)).text(this.text); + }; + + Button.prototype.render = function() { + this.wrapper = $(this._tpl.item).appendTo(this.editor.toolbar.list); + this.el = this.wrapper.find('a.toolbar-item'); + this.el.attr('title', this.title).addClass("toolbar-item-" + this.name).data('button', this); + this.setIcon(this.icon); + if (!this.menu) { + return; + } + this.menuWrapper = $(this._tpl.menuWrapper).appendTo(this.wrapper); + this.menuWrapper.addClass("toolbar-menu-" + this.name); + return this.renderMenu(); + }; + + Button.prototype.renderMenu = function() { + var $menuBtnEl, $menuItemEl, k, len, menuItem, ref, ref1, results; + if (!$.isArray(this.menu)) { + return; + } + this.menuEl = $('
        ').appendTo(this.menuWrapper); + ref = this.menu; + results = []; + for (k = 0, len = ref.length; k < len; k++) { + menuItem = ref[k]; + if (menuItem === '|') { + $(this._tpl.separator).appendTo(this.menuEl); + continue; + } + $menuItemEl = $(this._tpl.menuItem).appendTo(this.menuEl); + $menuBtnEl = $menuItemEl.find('a.menu-item').attr({ + 'title': (ref1 = menuItem.title) != null ? ref1 : menuItem.text, + 'data-param': menuItem.param + }).addClass('menu-item-' + menuItem.name); + if (menuItem.icon) { + results.push($menuBtnEl.find('span').addClass(this.iconClassOf(menuItem.icon))); + } else { + results.push($menuBtnEl.find('span').text(menuItem.text)); + } + } + return results; + }; + + Button.prototype.setActive = function(active) { + if (active === this.active) { + return; + } + this.active = active; + return this.el.toggleClass('active', this.active); + }; + + Button.prototype.setDisabled = function(disabled) { + if (disabled === this.disabled) { + return; + } + this.disabled = disabled; + return this.el.toggleClass('disabled', this.disabled); + }; + + Button.prototype._disableStatus = function() { + var disabled, endNodes, startNodes; + startNodes = this.editor.selection.startNodes(); + endNodes = this.editor.selection.endNodes(); + disabled = startNodes.filter(this.disableTag).length > 0 || endNodes.filter(this.disableTag).length > 0; + this.setDisabled(disabled); + if (this.disabled) { + this.setActive(false); + } + return this.disabled; + }; + + Button.prototype._activeStatus = function() { + var active, endNode, endNodes, startNode, startNodes; + startNodes = this.editor.selection.startNodes(); + endNodes = this.editor.selection.endNodes(); + startNode = startNodes.filter(this.htmlTag); + endNode = endNodes.filter(this.htmlTag); + active = startNode.length > 0 && endNode.length > 0 && startNode.is(endNode); + this.node = active ? startNode : null; + this.setActive(active); + return this.active; + }; + + Button.prototype._status = function() { + this._disableStatus(); + if (this.disabled) { + return; + } + return this._activeStatus(); + }; + + Button.prototype.command = function(param) {}; + + Button.prototype._t = function() { + var args, ref, result; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + result = Button.__super__._t.apply(this, args); + if (!result) { + result = (ref = this.editor)._t.apply(ref, args); + } + return result; + }; + + return Button; + +})(SimpleModule); + +Simditor.Button = Button; + +Popover = (function(superClass) { + extend(Popover, superClass); + + Popover.prototype.offset = { + top: 4, + left: 0 + }; + + Popover.prototype.target = null; + + Popover.prototype.active = false; + + function Popover(opts) { + this.button = opts.button; + this.editor = opts.button.editor; + Popover.__super__.constructor.call(this, opts); + } + + Popover.prototype._init = function() { + this.el = $('
        ').appendTo(this.editor.el).data('popover', this); + this.render(); + this.el.on('mouseenter', (function(_this) { + return function(e) { + return _this.el.addClass('hover'); + }; + })(this)); + return this.el.on('mouseleave', (function(_this) { + return function(e) { + return _this.el.removeClass('hover'); + }; + })(this)); + }; + + Popover.prototype.render = function() {}; + + Popover.prototype._initLabelWidth = function() { + var $fields; + $fields = this.el.find('.settings-field'); + if (!($fields.length > 0)) { + return; + } + this._labelWidth = 0; + $fields.each((function(_this) { + return function(i, field) { + var $field, $label; + $field = $(field); + $label = $field.find('label'); + if (!($label.length > 0)) { + return; + } + return _this._labelWidth = Math.max(_this._labelWidth, $label.width()); + }; + })(this)); + return $fields.find('label').width(this._labelWidth); + }; + + Popover.prototype.show = function($target, position) { + if (position == null) { + position = 'bottom'; + } + if ($target == null) { + return; + } + this.el.siblings('.simditor-popover').each(function(i, popover) { + popover = $(popover).data('popover'); + if (popover.active) { + return popover.hide(); + } + }); + if (this.active && this.target) { + this.target.removeClass('selected'); + } + this.target = $target.addClass('selected'); + if (this.active) { + this.refresh(position); + return this.trigger('popovershow'); + } else { + this.active = true; + this.el.css({ + left: -9999 + }).show(); + if (!this._labelWidth) { + this._initLabelWidth(); + } + this.editor.util.reflow(); + this.refresh(position); + return this.trigger('popovershow'); + } + }; + + Popover.prototype.hide = function() { + if (!this.active) { + return; + } + if (this.target) { + this.target.removeClass('selected'); + } + this.target = null; + this.active = false; + this.el.hide(); + return this.trigger('popoverhide'); + }; + + Popover.prototype.refresh = function(position) { + var editorOffset, left, maxLeft, targetH, targetOffset, top; + if (position == null) { + position = 'bottom'; + } + if (!this.active) { + return; + } + editorOffset = this.editor.el.offset(); + targetOffset = this.target.offset(); + targetH = this.target.outerHeight(); + if (position === 'bottom') { + top = targetOffset.top - editorOffset.top + targetH; + } else if (position === 'top') { + top = targetOffset.top - editorOffset.top - this.el.height(); + } + maxLeft = this.editor.wrapper.width() - this.el.outerWidth() - 10; + left = Math.min(targetOffset.left - editorOffset.left, maxLeft); + return this.el.css({ + top: top + this.offset.top, + left: left + this.offset.left + }); + }; + + Popover.prototype.destroy = function() { + this.target = null; + this.active = false; + this.editor.off('.linkpopover'); + return this.el.remove(); + }; + + Popover.prototype._t = function() { + var args, ref, result; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + result = Popover.__super__._t.apply(this, args); + if (!result) { + result = (ref = this.button)._t.apply(ref, args); + } + return result; + }; + + return Popover; + +})(SimpleModule); + +Simditor.Popover = Popover; + +TitleButton = (function(superClass) { + extend(TitleButton, superClass); + + function TitleButton() { + return TitleButton.__super__.constructor.apply(this, arguments); + } + + TitleButton.prototype.name = 'title'; + + TitleButton.prototype.htmlTag = 'h1, h2, h3, h4, h5'; + + TitleButton.prototype.disableTag = 'pre, table'; + + TitleButton.prototype._init = function() { + this.menu = [ + { + name: 'normal', + text: this._t('normalText'), + param: 'p' + }, '|', { + name: 'h1', + text: this._t('title') + ' 1', + param: 'h1' + }, { + name: 'h2', + text: this._t('title') + ' 2', + param: 'h2' + }, { + name: 'h3', + text: this._t('title') + ' 3', + param: 'h3' + }, { + name: 'h4', + text: this._t('title') + ' 4', + param: 'h4' + }, { + name: 'h5', + text: this._t('title') + ' 5', + param: 'h5' + } + ]; + return TitleButton.__super__._init.call(this); + }; + + TitleButton.prototype.setActive = function(active, param) { + TitleButton.__super__.setActive.call(this, active); + if (active) { + param || (param = this.node[0].tagName.toLowerCase()); + } + this.el.removeClass('active-p active-h1 active-h2 active-h3 active-h4 active-h5'); + if (active) { + return this.el.addClass('active active-' + param); + } + }; + + TitleButton.prototype.command = function(param) { + var $rootNodes; + $rootNodes = this.editor.selection.rootNodes(); + this.editor.selection.save(); + $rootNodes.each((function(_this) { + return function(i, node) { + var $node; + $node = $(node); + if ($node.is('blockquote') || $node.is(param) || $node.is(_this.disableTag) || _this.editor.util.isDecoratedNode($node)) { + return; + } + return $('<' + param + '/>').append($node.contents()).replaceAll($node); + }; + })(this)); + this.editor.selection.restore(); + return this.editor.trigger('valuechanged'); + }; + + return TitleButton; + +})(Button); + +Simditor.Toolbar.addButton(TitleButton); + +FontScaleButton = (function(superClass) { + extend(FontScaleButton, superClass); + + function FontScaleButton() { + return FontScaleButton.__super__.constructor.apply(this, arguments); + } + + FontScaleButton.prototype.name = 'fontScale'; + + FontScaleButton.prototype.icon = 'font'; + + FontScaleButton.prototype.disableTag = 'pre'; + + FontScaleButton.prototype.htmlTag = 'span'; + + FontScaleButton.prototype.sizeMap = { + 'x-large': '1.5em', + 'large': '1.25em', + 'small': '.75em', + 'x-small': '.5em' + }; + + FontScaleButton.prototype._init = function() { + this.menu = [ + { + name: '150%', + text: this._t('fontScaleXLarge'), + param: '5' + }, { + name: '125%', + text: this._t('fontScaleLarge'), + param: '4' + }, { + name: '100%', + text: this._t('fontScaleNormal'), + param: '3' + }, { + name: '75%', + text: this._t('fontScaleSmall'), + param: '2' + }, { + name: '50%', + text: this._t('fontScaleXSmall'), + param: '1' + } + ]; + return FontScaleButton.__super__._init.call(this); + }; + + FontScaleButton.prototype._activeStatus = function() { + var active, endNode, endNodes, range, startNode, startNodes; + range = this.editor.selection.range(); + startNodes = this.editor.selection.startNodes(); + endNodes = this.editor.selection.endNodes(); + startNode = startNodes.filter('span[style*="font-size"]'); + endNode = endNodes.filter('span[style*="font-size"]'); + active = startNodes.length > 0 && endNodes.length > 0 && startNode.is(endNode); + this.setActive(active); + return this.active; + }; + + FontScaleButton.prototype.command = function(param) { + var $scales, containerNode, range; + range = this.editor.selection.range(); + if (range.collapsed) { + return; + } + document.execCommand('styleWithCSS', false, true); + document.execCommand('fontSize', false, param); + document.execCommand('styleWithCSS', false, false); + this.editor.selection.reset(); + this.editor.selection.range(); + containerNode = this.editor.selection.containerNode(); + if (containerNode[0].nodeType === Node.TEXT_NODE) { + $scales = containerNode.closest('span[style*="font-size"]'); + } else { + $scales = containerNode.find('span[style*="font-size"]'); + } + $scales.each((function(_this) { + return function(i, n) { + var $span, size; + $span = $(n); + size = n.style.fontSize; + if (/large|x-large|small|x-small/.test(size)) { + return $span.css('fontSize', _this.sizeMap[size]); + } else if (size === 'medium') { + return $span.replaceWith($span.contents()); + } + }; + })(this)); + return this.editor.trigger('valuechanged'); + }; + + return FontScaleButton; + +})(Button); + +Simditor.Toolbar.addButton(FontScaleButton); + +BoldButton = (function(superClass) { + extend(BoldButton, superClass); + + function BoldButton() { + return BoldButton.__super__.constructor.apply(this, arguments); + } + + BoldButton.prototype.name = 'bold'; + + BoldButton.prototype.icon = 'bold'; + + BoldButton.prototype.htmlTag = 'b, strong'; + + BoldButton.prototype.disableTag = 'pre'; + + BoldButton.prototype.shortcut = 'cmd+b'; + + BoldButton.prototype._init = function() { + if (this.editor.util.os.mac) { + this.title = this.title + ' ( Cmd + b )'; + } else { + this.title = this.title + ' ( Ctrl + b )'; + this.shortcut = 'ctrl+b'; + } + return BoldButton.__super__._init.call(this); + }; + + BoldButton.prototype._activeStatus = function() { + var active; + active = document.queryCommandState('bold') === true; + this.setActive(active); + return this.active; + }; + + BoldButton.prototype.command = function() { + document.execCommand('bold'); + if (!this.editor.util.support.oninput) { + this.editor.trigger('valuechanged'); + } + return $(document).trigger('selectionchange'); + }; + + return BoldButton; + +})(Button); + +Simditor.Toolbar.addButton(BoldButton); + +ItalicButton = (function(superClass) { + extend(ItalicButton, superClass); + + function ItalicButton() { + return ItalicButton.__super__.constructor.apply(this, arguments); + } + + ItalicButton.prototype.name = 'italic'; + + ItalicButton.prototype.icon = 'italic'; + + ItalicButton.prototype.htmlTag = 'i'; + + ItalicButton.prototype.disableTag = 'pre'; + + ItalicButton.prototype.shortcut = 'cmd+i'; + + ItalicButton.prototype._init = function() { + if (this.editor.util.os.mac) { + this.title = this.title + " ( Cmd + i )"; + } else { + this.title = this.title + " ( Ctrl + i )"; + this.shortcut = 'ctrl+i'; + } + return ItalicButton.__super__._init.call(this); + }; + + ItalicButton.prototype._activeStatus = function() { + var active; + active = document.queryCommandState('italic') === true; + this.setActive(active); + return this.active; + }; + + ItalicButton.prototype.command = function() { + document.execCommand('italic'); + if (!this.editor.util.support.oninput) { + this.editor.trigger('valuechanged'); + } + return $(document).trigger('selectionchange'); + }; + + return ItalicButton; + +})(Button); + +Simditor.Toolbar.addButton(ItalicButton); + +UnderlineButton = (function(superClass) { + extend(UnderlineButton, superClass); + + function UnderlineButton() { + return UnderlineButton.__super__.constructor.apply(this, arguments); + } + + UnderlineButton.prototype.name = 'underline'; + + UnderlineButton.prototype.icon = 'underline'; + + UnderlineButton.prototype.htmlTag = 'u'; + + UnderlineButton.prototype.disableTag = 'pre'; + + UnderlineButton.prototype.shortcut = 'cmd+u'; + + UnderlineButton.prototype.render = function() { + if (this.editor.util.os.mac) { + this.title = this.title + ' ( Cmd + u )'; + } else { + this.title = this.title + ' ( Ctrl + u )'; + this.shortcut = 'ctrl+u'; + } + return UnderlineButton.__super__.render.call(this); + }; + + UnderlineButton.prototype._activeStatus = function() { + var active; + active = document.queryCommandState('underline') === true; + this.setActive(active); + return this.active; + }; + + UnderlineButton.prototype.command = function() { + document.execCommand('underline'); + if (!this.editor.util.support.oninput) { + this.editor.trigger('valuechanged'); + } + return $(document).trigger('selectionchange'); + }; + + return UnderlineButton; + +})(Button); + +Simditor.Toolbar.addButton(UnderlineButton); + +ColorButton = (function(superClass) { + extend(ColorButton, superClass); + + function ColorButton() { + return ColorButton.__super__.constructor.apply(this, arguments); + } + + ColorButton.prototype.name = 'color'; + + ColorButton.prototype.icon = 'tint'; + + ColorButton.prototype.disableTag = 'pre'; + + ColorButton.prototype.menu = true; + + ColorButton.prototype.render = function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return ColorButton.__super__.render.apply(this, args); + }; + + ColorButton.prototype.renderMenu = function() { + $('
          \n
        • \n
        • \n
        • \n
        • \n
        • \n
        • \n
        • \n
        • \n
        ').appendTo(this.menuWrapper); + this.menuWrapper.on('mousedown', '.color-list', function(e) { + return false; + }); + return this.menuWrapper.on('click', '.font-color', (function(_this) { + return function(e) { + var $link, $p, hex, range, rgb, textNode; + _this.wrapper.removeClass('menu-on'); + $link = $(e.currentTarget); + if ($link.hasClass('font-color-default')) { + $p = _this.editor.body.find('p, li'); + if (!($p.length > 0)) { + return; + } + rgb = window.getComputedStyle($p[0], null).getPropertyValue('color'); + hex = _this._convertRgbToHex(rgb); + } else { + rgb = window.getComputedStyle($link[0], null).getPropertyValue('background-color'); + hex = _this._convertRgbToHex(rgb); + } + if (!hex) { + return; + } + range = _this.editor.selection.range(); + if (!$link.hasClass('font-color-default') && range.collapsed) { + textNode = document.createTextNode(_this._t('coloredText')); + range.insertNode(textNode); + range.selectNodeContents(textNode); + _this.editor.selection.range(range); + } + document.execCommand('styleWithCSS', false, true); + document.execCommand('foreColor', false, hex); + document.execCommand('styleWithCSS', false, false); + if (!_this.editor.util.support.oninput) { + return _this.editor.trigger('valuechanged'); + } + }; + })(this)); + }; + + ColorButton.prototype._convertRgbToHex = function(rgb) { + var match, re, rgbToHex; + re = /rgb\((\d+),\s?(\d+),\s?(\d+)\)/g; + match = re.exec(rgb); + if (!match) { + return ''; + } + rgbToHex = function(r, g, b) { + var componentToHex; + componentToHex = function(c) { + var hex; + hex = c.toString(16); + if (hex.length === 1) { + return '0' + hex; + } else { + return hex; + } + }; + return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); + }; + return rgbToHex(match[1] * 1, match[2] * 1, match[3] * 1); + }; + + return ColorButton; + +})(Button); + +Simditor.Toolbar.addButton(ColorButton); + +ListButton = (function(superClass) { + extend(ListButton, superClass); + + function ListButton() { + return ListButton.__super__.constructor.apply(this, arguments); + } + + ListButton.prototype.type = ''; + + ListButton.prototype.disableTag = 'pre, table'; + + ListButton.prototype.command = function(param) { + var $list, $rootNodes, anotherType; + $rootNodes = this.editor.selection.blockNodes(); + anotherType = this.type === 'ul' ? 'ol' : 'ul'; + this.editor.selection.save(); + $list = null; + $rootNodes.each((function(_this) { + return function(i, node) { + var $node; + $node = $(node); + if ($node.is('blockquote, li') || $node.is(_this.disableTag) || _this.editor.util.isDecoratedNode($node) || !$.contains(document, node)) { + return; + } + if ($node.is(_this.type)) { + $node.children('li').each(function(i, li) { + var $childList, $li; + $li = $(li); + $childList = $li.children('ul, ol').insertAfter($node); + return $('

        ').append($(li).html() || _this.editor.util.phBr).insertBefore($node); + }); + return $node.remove(); + } else if ($node.is(anotherType)) { + return $('<' + _this.type + '/>').append($node.contents()).replaceAll($node); + } else if ($list && $node.prev().is($list)) { + $('

      • ').append($node.html() || _this.editor.util.phBr).appendTo($list); + return $node.remove(); + } else { + $list = $("<" + _this.type + ">
      • "); + $list.find('li').append($node.html() || _this.editor.util.phBr); + return $list.replaceAll($node); + } + }; + })(this)); + this.editor.selection.restore(); + return this.editor.trigger('valuechanged'); + }; + + return ListButton; + +})(Button); + +OrderListButton = (function(superClass) { + extend(OrderListButton, superClass); + + function OrderListButton() { + return OrderListButton.__super__.constructor.apply(this, arguments); + } + + OrderListButton.prototype.type = 'ol'; + + OrderListButton.prototype.name = 'ol'; + + OrderListButton.prototype.icon = 'list-ol'; + + OrderListButton.prototype.htmlTag = 'ol'; + + OrderListButton.prototype.shortcut = 'cmd+/'; + + OrderListButton.prototype._init = function() { + if (this.editor.util.os.mac) { + this.title = this.title + ' ( Cmd + / )'; + } else { + this.title = this.title + ' ( ctrl + / )'; + this.shortcut = 'ctrl+/'; + } + return OrderListButton.__super__._init.call(this); + }; + + return OrderListButton; + +})(ListButton); + +UnorderListButton = (function(superClass) { + extend(UnorderListButton, superClass); + + function UnorderListButton() { + return UnorderListButton.__super__.constructor.apply(this, arguments); + } + + UnorderListButton.prototype.type = 'ul'; + + UnorderListButton.prototype.name = 'ul'; + + UnorderListButton.prototype.icon = 'list-ul'; + + UnorderListButton.prototype.htmlTag = 'ul'; + + UnorderListButton.prototype.shortcut = 'cmd+.'; + + UnorderListButton.prototype._init = function() { + if (this.editor.util.os.mac) { + this.title = this.title + ' ( Cmd + . )'; + } else { + this.title = this.title + ' ( Ctrl + . )'; + this.shortcut = 'ctrl+.'; + } + return UnorderListButton.__super__._init.call(this); + }; + + return UnorderListButton; + +})(ListButton); + +Simditor.Toolbar.addButton(OrderListButton); + +Simditor.Toolbar.addButton(UnorderListButton); + +BlockquoteButton = (function(superClass) { + extend(BlockquoteButton, superClass); + + function BlockquoteButton() { + return BlockquoteButton.__super__.constructor.apply(this, arguments); + } + + BlockquoteButton.prototype.name = 'blockquote'; + + BlockquoteButton.prototype.icon = 'quote-left'; + + BlockquoteButton.prototype.htmlTag = 'blockquote'; + + BlockquoteButton.prototype.disableTag = 'pre, table'; + + BlockquoteButton.prototype.command = function() { + var $rootNodes, clearCache, nodeCache; + $rootNodes = this.editor.selection.rootNodes(); + $rootNodes = $rootNodes.filter(function(i, node) { + return !$(node).parent().is('blockquote'); + }); + this.editor.selection.save(); + nodeCache = []; + clearCache = (function(_this) { + return function() { + if (nodeCache.length > 0) { + $("<" + _this.htmlTag + "/>").insertBefore(nodeCache[0]).append(nodeCache); + return nodeCache.length = 0; + } + }; + })(this); + $rootNodes.each((function(_this) { + return function(i, node) { + var $node; + $node = $(node); + if (!$node.parent().is(_this.editor.body)) { + return; + } + if ($node.is(_this.htmlTag)) { + clearCache(); + return $node.children().unwrap(); + } else if ($node.is(_this.disableTag) || _this.editor.util.isDecoratedNode($node)) { + return clearCache(); + } else { + return nodeCache.push(node); + } + }; + })(this)); + clearCache(); + this.editor.selection.restore(); + return this.editor.trigger('valuechanged'); + }; + + return BlockquoteButton; + +})(Button); + +Simditor.Toolbar.addButton(BlockquoteButton); + +CodeButton = (function(superClass) { + extend(CodeButton, superClass); + + function CodeButton() { + return CodeButton.__super__.constructor.apply(this, arguments); + } + + CodeButton.prototype.name = 'code'; + + CodeButton.prototype.icon = 'code'; + + CodeButton.prototype.htmlTag = 'pre'; + + CodeButton.prototype.disableTag = 'ul, ol, table'; + + CodeButton.prototype._init = function() { + CodeButton.__super__._init.call(this); + this.editor.on('decorate', (function(_this) { + return function(e, $el) { + return $el.find('pre').each(function(i, pre) { + return _this.decorate($(pre)); + }); + }; + })(this)); + return this.editor.on('undecorate', (function(_this) { + return function(e, $el) { + return $el.find('pre').each(function(i, pre) { + return _this.undecorate($(pre)); + }); + }; + })(this)); + }; + + CodeButton.prototype.render = function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + CodeButton.__super__.render.apply(this, args); + return this.popover = new CodePopover({ + button: this + }); + }; + + CodeButton.prototype._checkMode = function() { + var $blockNodes, range; + range = this.editor.selection.range(); + if (($blockNodes = $(range.cloneContents()).find(this.editor.util.blockNodes.join(','))) > 0 || (range.collapsed && this.editor.selection.startNodes().filter('code').length === 0)) { + this.inlineMode = false; + return this.htmlTag = 'pre'; + } else { + this.inlineMode = true; + return this.htmlTag = 'code'; + } + }; + + CodeButton.prototype._status = function() { + this._checkMode(); + CodeButton.__super__._status.call(this); + if (this.inlineMode) { + return; + } + if (this.active) { + return this.popover.show(this.node); + } else { + return this.popover.hide(); + } + }; + + CodeButton.prototype.decorate = function($pre) { + var $code, lang, ref, ref1; + $code = $pre.find('> code'); + if ($code.length > 0) { + lang = (ref = $code.attr('class')) != null ? (ref1 = ref.match(/lang-(\S+)/)) != null ? ref1[1] : void 0 : void 0; + $code.contents().unwrap(); + if (lang) { + return $pre.attr('data-lang', lang); + } + } + }; + + CodeButton.prototype.undecorate = function($pre) { + var $code, lang; + lang = $pre.attr('data-lang'); + $code = $(''); + if (lang && lang !== -1) { + $code.addClass('lang-' + lang); + } + return $pre.wrapInner($code).removeAttr('data-lang'); + }; + + CodeButton.prototype.command = function() { + if (this.inlineMode) { + return this._inlineCommand(); + } else { + return this._blockCommand(); + } + }; + + CodeButton.prototype._blockCommand = function() { + var $rootNodes, clearCache, nodeCache, resultNodes; + $rootNodes = this.editor.selection.rootNodes(); + nodeCache = []; + resultNodes = []; + clearCache = (function(_this) { + return function() { + var $pre; + if (!(nodeCache.length > 0)) { + return; + } + $pre = $("<" + _this.htmlTag + "/>").insertBefore(nodeCache[0]).text(_this.editor.formatter.clearHtml(nodeCache)); + resultNodes.push($pre[0]); + return nodeCache.length = 0; + }; + })(this); + $rootNodes.each((function(_this) { + return function(i, node) { + var $node, $p; + $node = $(node); + if ($node.is(_this.htmlTag)) { + clearCache(); + $p = $('

        ').append($node.html().replace('\n', '
        ')).replaceAll($node); + return resultNodes.push($p[0]); + } else if ($node.is(_this.disableTag) || _this.editor.util.isDecoratedNode($node) || $node.is('blockquote')) { + return clearCache(); + } else { + return nodeCache.push(node); + } + }; + })(this)); + clearCache(); + this.editor.selection.setRangeAtEndOf($(resultNodes).last()); + return this.editor.trigger('valuechanged'); + }; + + CodeButton.prototype._inlineCommand = function() { + var $code, $contents, range; + range = this.editor.selection.range(); + if (this.active) { + range.selectNodeContents(this.node[0]); + this.editor.selection.save(range); + this.node.contents().unwrap(); + this.editor.selection.restore(); + } else { + $contents = $(range.extractContents()); + $code = $("<" + this.htmlTag + "/>").append($contents.contents()); + range.insertNode($code[0]); + range.selectNodeContents($code[0]); + this.editor.selection.range(range); + } + return this.editor.trigger('valuechanged'); + }; + + return CodeButton; + +})(Button); + +CodePopover = (function(superClass) { + extend(CodePopover, superClass); + + function CodePopover() { + return CodePopover.__super__.constructor.apply(this, arguments); + } + + CodePopover.prototype.render = function() { + var $option, k, lang, len, ref; + this._tpl = "

        \n
        \n \n
        \n
        "; + this.langs = this.editor.opts.codeLanguages || [ + { + name: 'Bash', + value: 'bash' + }, { + name: 'C++', + value: 'c++' + }, { + name: 'C#', + value: 'cs' + }, { + name: 'CSS', + value: 'css' + }, { + name: 'Erlang', + value: 'erlang' + }, { + name: 'Less', + value: 'less' + }, { + name: 'Sass', + value: 'sass' + }, { + name: 'Diff', + value: 'diff' + }, { + name: 'CoffeeScript', + value: 'coffeescript' + }, { + name: 'HTML,XML', + value: 'html' + }, { + name: 'JSON', + value: 'json' + }, { + name: 'Java', + value: 'java' + }, { + name: 'JavaScript', + value: 'js' + }, { + name: 'Markdown', + value: 'markdown' + }, { + name: 'Objective C', + value: 'oc' + }, { + name: 'PHP', + value: 'php' + }, { + name: 'Perl', + value: 'parl' + }, { + name: 'Python', + value: 'python' + }, { + name: 'Ruby', + value: 'ruby' + }, { + name: 'SQL', + value: 'sql' + } + ]; + this.el.addClass('code-popover').append(this._tpl); + this.selectEl = this.el.find('.select-lang'); + ref = this.langs; + for (k = 0, len = ref.length; k < len; k++) { + lang = ref[k]; + $option = $('