diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..53fb05154
Binary files /dev/null and b/.DS_Store differ
diff --git a/public/css/.DS_Store b/public/css/.DS_Store
new file mode 100644
index 000000000..5008ddfcf
Binary files /dev/null and b/public/css/.DS_Store differ
diff --git a/public/css/simditor.css b/public/css/simditor.css
new file mode 100644
index 000000000..341ae827d
--- /dev/null
+++ b/public/css/simditor.css
@@ -0,0 +1,746 @@
+/*!
+* Simditor v2.3.6
+* http://simditor.tower.im/
+* 2015-12-21
+*/
+@font-face {
+ font-family: 'Simditor';
+ src: url(data:application/font-woff;charset=utf-8;base64,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) format("woff");
+ font-weight: normal;
+ font-style: normal;
+}
+.simditor-icon {
+ display: inline-block;
+ font: normal normal normal 14px/1 'Simditor';
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ transform: translate(0, 0);
+}
+
+.simditor-icon-code:before {
+ content: '\f000';
+}
+
+.simditor-icon-bold:before {
+ content: '\f001';
+}
+
+.simditor-icon-italic:before {
+ content: '\f002';
+}
+
+.simditor-icon-underline:before {
+ content: '\f003';
+}
+
+.simditor-icon-times:before {
+ content: '\f004';
+}
+
+.simditor-icon-strikethrough:before {
+ content: '\f005';
+}
+
+.simditor-icon-list-ol:before {
+ content: '\f006';
+}
+
+.simditor-icon-list-ul:before {
+ content: '\f007';
+}
+
+.simditor-icon-quote-left:before {
+ content: '\f008';
+}
+
+.simditor-icon-table:before {
+ content: '\f009';
+}
+
+.simditor-icon-link:before {
+ content: '\f00a';
+}
+
+.simditor-icon-picture-o:before {
+ content: '\f00b';
+}
+
+.simditor-icon-minus:before {
+ content: '\f00c';
+}
+
+.simditor-icon-indent:before {
+ content: '\f00d';
+}
+
+.simditor-icon-outdent:before {
+ content: '\f00e';
+}
+
+.simditor-icon-unlink:before {
+ content: '\f00f';
+}
+
+.simditor-icon-caret-down:before {
+ content: '\f010';
+}
+
+.simditor-icon-caret-right:before {
+ content: '\f011';
+}
+
+.simditor-icon-upload:before {
+ content: '\f012';
+}
+
+.simditor-icon-undo:before {
+ content: '\f013';
+}
+
+.simditor-icon-smile-o:before {
+ content: '\f014';
+}
+
+.simditor-icon-tint:before {
+ content: '\f015';
+}
+
+.simditor-icon-font:before {
+ content: '\f016';
+}
+
+.simditor-icon-html5:before {
+ content: '\f017';
+}
+
+.simditor-icon-mark:before {
+ content: '\f018';
+}
+
+.simditor-icon-align-center:before {
+ content: '\f019';
+}
+
+.simditor-icon-align-left:before {
+ content: '\f01a';
+}
+
+.simditor-icon-align-right:before {
+ content: '\f01b';
+}
+
+.simditor-icon-font-minus:before {
+ content: '\f01c';
+}
+
+.simditor-icon-markdown:before {
+ content: '\f01d';
+}
+
+.simditor-icon-checklist:before {
+ content: '\f01e';
+}
+
+.simditor {
+ position: relative;
+ border: 1px solid #c9d8db;
+}
+.simditor .simditor-wrapper {
+ position: relative;
+ background: #ffffff;
+}
+.simditor .simditor-wrapper > 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 = "";
+
+ 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 + ">" + _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 = $('', {
+ text: lang.name,
+ value: lang.value
+ }).appendTo(this.selectEl);
+ }
+ this.selectEl.on('change', (function(_this) {
+ return function(e) {
+ var selected;
+ _this.lang = _this.selectEl.val();
+ selected = _this.target.hasClass('selected');
+ _this.target.removeClass().removeAttr('data-lang');
+ if (_this.lang !== -1) {
+ _this.target.attr('data-lang', _this.lang);
+ }
+ if (selected) {
+ _this.target.addClass('selected');
+ }
+ return _this.editor.trigger('valuechanged');
+ };
+ })(this));
+ return this.editor.on('valuechanged', (function(_this) {
+ return function(e) {
+ if (_this.active) {
+ return _this.refresh();
+ }
+ };
+ })(this));
+ };
+
+ CodePopover.prototype.show = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ CodePopover.__super__.show.apply(this, args);
+ this.lang = this.target.attr('data-lang');
+ if (this.lang != null) {
+ return this.selectEl.val(this.lang);
+ } else {
+ return this.selectEl.val(-1);
+ }
+ };
+
+ return CodePopover;
+
+})(Popover);
+
+Simditor.Toolbar.addButton(CodeButton);
+
+LinkButton = (function(superClass) {
+ extend(LinkButton, superClass);
+
+ function LinkButton() {
+ return LinkButton.__super__.constructor.apply(this, arguments);
+ }
+
+ LinkButton.prototype.name = 'link';
+
+ LinkButton.prototype.icon = 'link';
+
+ LinkButton.prototype.htmlTag = 'a';
+
+ LinkButton.prototype.disableTag = 'pre';
+
+ LinkButton.prototype.render = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ LinkButton.__super__.render.apply(this, args);
+ return this.popover = new LinkPopover({
+ button: this
+ });
+ };
+
+ LinkButton.prototype._status = function() {
+ LinkButton.__super__._status.call(this);
+ if (this.active && !this.editor.selection.rangeAtEndOf(this.node)) {
+ return this.popover.show(this.node);
+ } else {
+ return this.popover.hide();
+ }
+ };
+
+ LinkButton.prototype.command = function() {
+ var $contents, $link, $newBlock, linkText, range, txtNode;
+ range = this.editor.selection.range();
+ if (this.active) {
+ txtNode = document.createTextNode(this.node.text());
+ this.node.replaceWith(txtNode);
+ range.selectNode(txtNode);
+ } else {
+ $contents = $(range.extractContents());
+ linkText = this.editor.formatter.clearHtml($contents.contents(), false);
+ $link = $('', {
+ href: 'http://www.example.com',
+ target: '_blank',
+ text: linkText || this._t('linkText')
+ });
+ if (this.editor.selection.blockNodes().length > 0) {
+ range.insertNode($link[0]);
+ } else {
+ $newBlock = $('').append($link);
+ range.insertNode($newBlock[0]);
+ }
+ range.selectNodeContents($link[0]);
+ this.popover.one('popovershow', (function(_this) {
+ return function() {
+ if (linkText) {
+ _this.popover.urlEl.focus();
+ return _this.popover.urlEl[0].select();
+ } else {
+ _this.popover.textEl.focus();
+ return _this.popover.textEl[0].select();
+ }
+ };
+ })(this));
+ }
+ this.editor.selection.range(range);
+ return this.editor.trigger('valuechanged');
+ };
+
+ return LinkButton;
+
+})(Button);
+
+LinkPopover = (function(superClass) {
+ extend(LinkPopover, superClass);
+
+ function LinkPopover() {
+ return LinkPopover.__super__.constructor.apply(this, arguments);
+ }
+
+ LinkPopover.prototype.render = function() {
+ var tpl;
+ tpl = "\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
";
+ this.el.addClass('link-popover').append(tpl);
+ this.textEl = this.el.find('.link-text');
+ this.urlEl = this.el.find('.link-url');
+ this.unlinkEl = this.el.find('.btn-unlink');
+ this.selectTarget = this.el.find('.link-target');
+ this.textEl.on('keyup', (function(_this) {
+ return function(e) {
+ if (e.which === 13) {
+ return;
+ }
+ _this.target.text(_this.textEl.val());
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ this.urlEl.on('keyup', (function(_this) {
+ return function(e) {
+ var val;
+ if (e.which === 13) {
+ return;
+ }
+ val = _this.urlEl.val();
+ if (!(/https?:\/\/|^\//ig.test(val) || !val)) {
+ val = 'http://' + val;
+ }
+ _this.target.attr('href', val);
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ $([this.urlEl[0], this.textEl[0]]).on('keydown', (function(_this) {
+ return function(e) {
+ var range;
+ if (e.which === 13 || e.which === 27 || (!e.shiftKey && e.which === 9 && $(e.target).hasClass('link-url'))) {
+ e.preventDefault();
+ range = document.createRange();
+ _this.editor.selection.setRangeAfter(_this.target, range);
+ _this.hide();
+ return _this.editor.inputManager.throttledValueChanged();
+ }
+ };
+ })(this));
+ this.unlinkEl.on('click', (function(_this) {
+ return function(e) {
+ var range, txtNode;
+ txtNode = document.createTextNode(_this.target.text());
+ _this.target.replaceWith(txtNode);
+ _this.hide();
+ range = document.createRange();
+ _this.editor.selection.setRangeAfter(txtNode, range);
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ return this.selectTarget.on('change', (function(_this) {
+ return function(e) {
+ _this.target.attr('target', _this.selectTarget.val());
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ };
+
+ LinkPopover.prototype.show = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ LinkPopover.__super__.show.apply(this, args);
+ this.textEl.val(this.target.text());
+ return this.urlEl.val(this.target.attr('href'));
+ };
+
+ return LinkPopover;
+
+})(Popover);
+
+Simditor.Toolbar.addButton(LinkButton);
+
+ImageButton = (function(superClass) {
+ extend(ImageButton, superClass);
+
+ function ImageButton() {
+ return ImageButton.__super__.constructor.apply(this, arguments);
+ }
+
+ ImageButton.prototype.name = 'image';
+
+ ImageButton.prototype.icon = 'picture-o';
+
+ ImageButton.prototype.htmlTag = 'img';
+
+ ImageButton.prototype.disableTag = 'pre, table';
+
+ ImageButton.prototype.defaultImage = '';
+
+ ImageButton.prototype.needFocus = false;
+
+ ImageButton.prototype._init = function() {
+ var item, k, len, ref;
+ if (this.editor.opts.imageButton) {
+ if (Array.isArray(this.editor.opts.imageButton)) {
+ this.menu = [];
+ ref = this.editor.opts.imageButton;
+ for (k = 0, len = ref.length; k < len; k++) {
+ item = ref[k];
+ this.menu.push({
+ name: item + '-image',
+ text: this._t(item + 'Image')
+ });
+ }
+ } else {
+ this.menu = false;
+ }
+ } else {
+ if (this.editor.uploader != null) {
+ this.menu = [
+ {
+ name: 'upload-image',
+ text: this._t('uploadImage')
+ }, {
+ name: 'external-image',
+ text: this._t('externalImage')
+ }
+ ];
+ } else {
+ this.menu = false;
+ }
+ }
+ this.defaultImage = this.editor.opts.defaultImage;
+ this.editor.body.on('click', 'img:not([data-non-image])', (function(_this) {
+ return function(e) {
+ var $img, range;
+ $img = $(e.currentTarget);
+ range = document.createRange();
+ range.selectNode($img[0]);
+ _this.editor.selection.range(range);
+ if (!_this.editor.util.support.onselectionchange) {
+ _this.editor.trigger('selectionchanged');
+ }
+ return false;
+ };
+ })(this));
+ this.editor.body.on('mouseup', 'img:not([data-non-image])', function(e) {
+ return false;
+ });
+ this.editor.on('selectionchanged.image', (function(_this) {
+ return function() {
+ var $contents, $img, range;
+ range = _this.editor.selection.range();
+ if (range == null) {
+ return;
+ }
+ $contents = $(range.cloneContents()).contents();
+ if ($contents.length === 1 && $contents.is('img:not([data-non-image])')) {
+ $img = $(range.startContainer).contents().eq(range.startOffset);
+ return _this.popover.show($img);
+ } else {
+ return _this.popover.hide();
+ }
+ };
+ })(this));
+ this.editor.on('valuechanged.image', (function(_this) {
+ return function() {
+ var $masks;
+ $masks = _this.editor.wrapper.find('.simditor-image-loading');
+ if (!($masks.length > 0)) {
+ return;
+ }
+ return $masks.each(function(i, mask) {
+ var $img, $mask, file;
+ $mask = $(mask);
+ $img = $mask.data('img');
+ if (!($img && $img.parent().length > 0)) {
+ $mask.remove();
+ if ($img) {
+ file = $img.data('file');
+ if (file) {
+ _this.editor.uploader.cancel(file);
+ if (_this.editor.body.find('img.uploading').length < 1) {
+ return _this.editor.uploader.trigger('uploadready', [file]);
+ }
+ }
+ }
+ }
+ });
+ };
+ })(this));
+ return ImageButton.__super__._init.call(this);
+ };
+
+ ImageButton.prototype.render = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ ImageButton.__super__.render.apply(this, args);
+ this.popover = new ImagePopover({
+ button: this
+ });
+ if (this.editor.opts.imageButton === 'upload') {
+ return this._initUploader(this.el);
+ }
+ };
+
+ ImageButton.prototype.renderMenu = function() {
+ ImageButton.__super__.renderMenu.call(this);
+ return this._initUploader();
+ };
+
+ ImageButton.prototype._initUploader = function($uploadItem) {
+ var $input, createInput, uploadProgress;
+ if ($uploadItem == null) {
+ $uploadItem = this.menuEl.find('.menu-item-upload-image');
+ }
+ if (this.editor.uploader == null) {
+ this.el.find('.btn-upload').remove();
+ return;
+ }
+ $input = null;
+ createInput = (function(_this) {
+ return function() {
+ if ($input) {
+ $input.remove();
+ }
+ return $input = $('', {
+ type: 'file',
+ title: _this._t('uploadImage'),
+ multiple: true,
+ accept: 'image/*'
+ }).appendTo($uploadItem);
+ };
+ })(this);
+ createInput();
+ $uploadItem.on('click mousedown', 'input[type=file]', function(e) {
+ return e.stopPropagation();
+ });
+ $uploadItem.on('change', 'input[type=file]', (function(_this) {
+ return function(e) {
+ if (_this.editor.inputManager.focused) {
+ _this.editor.uploader.upload($input, {
+ inline: true
+ });
+ createInput();
+ } else {
+ _this.editor.one('focus', function(e) {
+ _this.editor.uploader.upload($input, {
+ inline: true
+ });
+ return createInput();
+ });
+ _this.editor.focus();
+ }
+ return _this.wrapper.removeClass('menu-on');
+ };
+ })(this));
+ this.editor.uploader.on('beforeupload', (function(_this) {
+ return function(e, file) {
+ var $img;
+ if (!file.inline) {
+ return;
+ }
+ if (file.img) {
+ $img = $(file.img);
+ } else {
+ $img = _this.createImage(file.name);
+ file.img = $img;
+ }
+ $img.addClass('uploading');
+ $img.data('file', file);
+ return _this.editor.uploader.readImageFile(file.obj, function(img) {
+ var src;
+ if (!$img.hasClass('uploading')) {
+ return;
+ }
+ src = img ? img.src : _this.defaultImage;
+ return _this.loadImage($img, src, function() {
+ if (_this.popover.active) {
+ _this.popover.refresh();
+ return _this.popover.srcEl.val(_this._t('uploading')).prop('disabled', true);
+ }
+ });
+ });
+ };
+ })(this));
+ uploadProgress = $.proxy(this.editor.util.throttle(function(e, file, loaded, total) {
+ var $img, $mask, percent;
+ if (!file.inline) {
+ return;
+ }
+ $mask = file.img.data('mask');
+ if (!$mask) {
+ return;
+ }
+ $img = $mask.data('img');
+ if (!($img.hasClass('uploading') && $img.parent().length > 0)) {
+ $mask.remove();
+ return;
+ }
+ percent = loaded / total;
+ percent = (percent * 100).toFixed(0);
+ if (percent > 99) {
+ percent = 99;
+ }
+ return $mask.find('.progress').height((100 - percent) + "%");
+ }, 500), this);
+ this.editor.uploader.on('uploadprogress', uploadProgress);
+ this.editor.uploader.on('uploadsuccess', (function(_this) {
+ return function(e, file, result) {
+ var $img, img_path, msg;
+ if (!file.inline) {
+ return;
+ }
+ $img = file.img;
+ if (!($img.hasClass('uploading') && $img.parent().length > 0)) {
+ return;
+ }
+ if (typeof result !== 'object') {
+ try {
+ result = $.parseJSON(result);
+ } catch (_error) {
+ e = _error;
+ result = {
+ success: false
+ };
+ }
+ }
+ if (result.success === false) {
+ msg = result.msg || _this._t('uploadFailed');
+ alert(msg);
+ img_path = _this.defaultImage;
+ } else {
+ img_path = result.file_path;
+ }
+ _this.loadImage($img, img_path, function() {
+ var $mask;
+ $img.removeData('file');
+ $img.removeClass('uploading').removeClass('loading');
+ $mask = $img.data('mask');
+ if ($mask) {
+ $mask.remove();
+ }
+ $img.removeData('mask');
+ _this.editor.trigger('valuechanged');
+ if (_this.editor.body.find('img.uploading').length < 1) {
+ return _this.editor.uploader.trigger('uploadready', [file, result]);
+ }
+ });
+ if (_this.popover.active) {
+ _this.popover.srcEl.prop('disabled', false);
+ return _this.popover.srcEl.val(result.file_path);
+ }
+ };
+ })(this));
+ return this.editor.uploader.on('uploaderror', (function(_this) {
+ return function(e, file, xhr) {
+ var $img, msg, result;
+ if (!file.inline) {
+ return;
+ }
+ if (xhr.statusText === 'abort') {
+ return;
+ }
+ if (xhr.responseText) {
+ try {
+ result = $.parseJSON(xhr.responseText);
+ msg = result.msg;
+ } catch (_error) {
+ e = _error;
+ msg = _this._t('uploadError');
+ }
+ alert(msg);
+ }
+ $img = file.img;
+ if (!($img.hasClass('uploading') && $img.parent().length > 0)) {
+ return;
+ }
+ _this.loadImage($img, _this.defaultImage, function() {
+ var $mask;
+ $img.removeData('file');
+ $img.removeClass('uploading').removeClass('loading');
+ $mask = $img.data('mask');
+ if ($mask) {
+ $mask.remove();
+ }
+ return $img.removeData('mask');
+ });
+ if (_this.popover.active) {
+ _this.popover.srcEl.prop('disabled', false);
+ _this.popover.srcEl.val(_this.defaultImage);
+ }
+ _this.editor.trigger('valuechanged');
+ if (_this.editor.body.find('img.uploading').length < 1) {
+ return _this.editor.uploader.trigger('uploadready', [file, result]);
+ }
+ };
+ })(this));
+ };
+
+ ImageButton.prototype._status = function() {
+ return this._disableStatus();
+ };
+
+ ImageButton.prototype.loadImage = function($img, src, callback) {
+ var $mask, img, positionMask;
+ positionMask = (function(_this) {
+ return function() {
+ var imgOffset, wrapperOffset;
+ imgOffset = $img.offset();
+ wrapperOffset = _this.editor.wrapper.offset();
+ return $mask.css({
+ top: imgOffset.top - wrapperOffset.top,
+ left: imgOffset.left - wrapperOffset.left,
+ width: $img.width(),
+ height: $img.height()
+ }).show();
+ };
+ })(this);
+ $img.addClass('loading');
+ $mask = $img.data('mask');
+ if (!$mask) {
+ $mask = $('').hide().appendTo(this.editor.wrapper);
+ positionMask();
+ $img.data('mask', $mask);
+ $mask.data('img', $img);
+ }
+ img = new Image();
+ img.onload = (function(_this) {
+ return function() {
+ var height, width;
+ if (!$img.hasClass('loading') && !$img.hasClass('uploading')) {
+ return;
+ }
+ width = img.width;
+ height = img.height;
+ $img.attr({
+ src: src,
+ width: width,
+ height: height,
+ 'data-image-size': width + ',' + height
+ }).removeClass('loading');
+ if ($img.hasClass('uploading')) {
+ _this.editor.util.reflow(_this.editor.body);
+ positionMask();
+ } else {
+ $mask.remove();
+ $img.removeData('mask');
+ }
+ if ($.isFunction(callback)) {
+ return callback(img);
+ }
+ };
+ })(this);
+ img.onerror = function() {
+ if ($.isFunction(callback)) {
+ callback(false);
+ }
+ $mask.remove();
+ return $img.removeData('mask').removeClass('loading');
+ };
+ return img.src = src;
+ };
+
+ ImageButton.prototype.createImage = function(name) {
+ var $img, range;
+ if (name == null) {
+ name = 'Image';
+ }
+ if (!this.editor.inputManager.focused) {
+ this.editor.focus();
+ }
+ range = this.editor.selection.range();
+ range.deleteContents();
+ this.editor.selection.range(range);
+ $img = $('
').attr('alt', name);
+ range.insertNode($img[0]);
+ this.editor.selection.setRangeAfter($img, range);
+ this.editor.trigger('valuechanged');
+ return $img;
+ };
+
+ ImageButton.prototype.command = function(src) {
+ var $img;
+ $img = this.createImage();
+ return this.loadImage($img, src || this.defaultImage, (function(_this) {
+ return function() {
+ _this.editor.trigger('valuechanged');
+ _this.editor.util.reflow($img);
+ $img.click();
+ return _this.popover.one('popovershow', function() {
+ _this.popover.srcEl.focus();
+ return _this.popover.srcEl[0].select();
+ });
+ };
+ })(this));
+ };
+
+ return ImageButton;
+
+})(Button);
+
+ImagePopover = (function(superClass) {
+ extend(ImagePopover, superClass);
+
+ function ImagePopover() {
+ return ImagePopover.__super__.constructor.apply(this, arguments);
+ }
+
+ ImagePopover.prototype.offset = {
+ top: 6,
+ left: -4
+ };
+
+ ImagePopover.prototype.render = function() {
+ var tpl;
+ tpl = "\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n
\n
×\n
\n
\n \n \n
\n
";
+ this.el.addClass('image-popover').append(tpl);
+ this.srcEl = this.el.find('.image-src');
+ this.widthEl = this.el.find('#image-width');
+ this.heightEl = this.el.find('#image-height');
+ this.altEl = this.el.find('#image-alt');
+ this.srcEl.on('keydown', (function(_this) {
+ return function(e) {
+ var range;
+ if (!(e.which === 13 && !_this.target.hasClass('uploading'))) {
+ return;
+ }
+ e.preventDefault();
+ range = document.createRange();
+ _this.button.editor.selection.setRangeAfter(_this.target, range);
+ return _this.hide();
+ };
+ })(this));
+ this.srcEl.on('blur', (function(_this) {
+ return function(e) {
+ return _this._loadImage(_this.srcEl.val());
+ };
+ })(this));
+ this.el.find('.image-size').on('blur', (function(_this) {
+ return function(e) {
+ _this._resizeImg($(e.currentTarget));
+ return _this.el.data('popover').refresh();
+ };
+ })(this));
+ this.el.find('.image-size').on('keyup', (function(_this) {
+ return function(e) {
+ var inputEl;
+ inputEl = $(e.currentTarget);
+ if (!(e.which === 13 || e.which === 27 || e.which === 9)) {
+ return _this._resizeImg(inputEl, true);
+ }
+ };
+ })(this));
+ this.el.find('.image-size').on('keydown', (function(_this) {
+ return function(e) {
+ var $img, inputEl, range;
+ inputEl = $(e.currentTarget);
+ if (e.which === 13 || e.which === 27) {
+ e.preventDefault();
+ if (e.which === 13) {
+ _this._resizeImg(inputEl);
+ } else {
+ _this._restoreImg();
+ }
+ $img = _this.target;
+ _this.hide();
+ range = document.createRange();
+ return _this.button.editor.selection.setRangeAfter($img, range);
+ } else if (e.which === 9) {
+ return _this.el.data('popover').refresh();
+ }
+ };
+ })(this));
+ this.altEl.on('keydown', (function(_this) {
+ return function(e) {
+ var range;
+ if (e.which === 13) {
+ e.preventDefault();
+ range = document.createRange();
+ _this.button.editor.selection.setRangeAfter(_this.target, range);
+ return _this.hide();
+ }
+ };
+ })(this));
+ this.altEl.on('keyup', (function(_this) {
+ return function(e) {
+ if (e.which === 13 || e.which === 27 || e.which === 9) {
+ return;
+ }
+ _this.alt = _this.altEl.val();
+ return _this.target.attr('alt', _this.alt);
+ };
+ })(this));
+ this.el.find('.btn-restore').on('click', (function(_this) {
+ return function(e) {
+ _this._restoreImg();
+ return _this.el.data('popover').refresh();
+ };
+ })(this));
+ this.editor.on('valuechanged', (function(_this) {
+ return function(e) {
+ if (_this.active) {
+ return _this.refresh();
+ }
+ };
+ })(this));
+ return this._initUploader();
+ };
+
+ ImagePopover.prototype._initUploader = function() {
+ var $uploadBtn, createInput;
+ $uploadBtn = this.el.find('.btn-upload');
+ if (this.editor.uploader == null) {
+ $uploadBtn.remove();
+ return;
+ }
+ createInput = (function(_this) {
+ return function() {
+ if (_this.input) {
+ _this.input.remove();
+ }
+ return _this.input = $('', {
+ type: 'file',
+ title: _this._t('uploadImage'),
+ multiple: true,
+ accept: 'image/*'
+ }).appendTo($uploadBtn);
+ };
+ })(this);
+ createInput();
+ this.el.on('click mousedown', 'input[type=file]', function(e) {
+ return e.stopPropagation();
+ });
+ return this.el.on('change', 'input[type=file]', (function(_this) {
+ return function(e) {
+ _this.editor.uploader.upload(_this.input, {
+ inline: true,
+ img: _this.target
+ });
+ return createInput();
+ };
+ })(this));
+ };
+
+ ImagePopover.prototype._resizeImg = function(inputEl, onlySetVal) {
+ var height, value, width;
+ if (onlySetVal == null) {
+ onlySetVal = false;
+ }
+ value = inputEl.val() * 1;
+ if (!(this.target && ($.isNumeric(value) || value < 0))) {
+ return;
+ }
+ if (inputEl.is(this.widthEl)) {
+ width = value;
+ height = this.height * value / this.width;
+ this.heightEl.val(height);
+ } else {
+ height = value;
+ width = this.width * value / this.height;
+ this.widthEl.val(width);
+ }
+ if (!onlySetVal) {
+ this.target.attr({
+ width: width,
+ height: height
+ });
+ return this.editor.trigger('valuechanged');
+ }
+ };
+
+ ImagePopover.prototype._restoreImg = function() {
+ var ref, size;
+ size = ((ref = this.target.data('image-size')) != null ? ref.split(",") : void 0) || [this.width, this.height];
+ this.target.attr({
+ width: size[0] * 1,
+ height: size[1] * 1
+ });
+ this.widthEl.val(size[0]);
+ this.heightEl.val(size[1]);
+ return this.editor.trigger('valuechanged');
+ };
+
+ ImagePopover.prototype._loadImage = function(src, callback) {
+ if (/^data:image/.test(src) && !this.editor.uploader) {
+ if (callback) {
+ callback(false);
+ }
+ return;
+ }
+ if (this.target.attr('src') === src) {
+ return;
+ }
+ return this.button.loadImage(this.target, src, (function(_this) {
+ return function(img) {
+ var blob;
+ if (!img) {
+ return;
+ }
+ if (_this.active) {
+ _this.width = img.width;
+ _this.height = img.height;
+ _this.widthEl.val(_this.width);
+ _this.heightEl.val(_this.height);
+ }
+ if (/^data:image/.test(src)) {
+ blob = _this.editor.util.dataURLtoBlob(src);
+ blob.name = "Base64 Image.png";
+ _this.editor.uploader.upload(blob, {
+ inline: true,
+ img: _this.target
+ });
+ } else {
+ _this.editor.trigger('valuechanged');
+ }
+ if (callback) {
+ return callback(img);
+ }
+ };
+ })(this));
+ };
+
+ ImagePopover.prototype.show = function() {
+ var $img, args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ ImagePopover.__super__.show.apply(this, args);
+ $img = this.target;
+ this.width = $img.width();
+ this.height = $img.height();
+ this.alt = $img.attr('alt');
+ if ($img.hasClass('uploading')) {
+ return this.srcEl.val(this._t('uploading')).prop('disabled', true);
+ } else {
+ this.srcEl.val($img.attr('src')).prop('disabled', false);
+ this.widthEl.val(this.width);
+ this.heightEl.val(this.height);
+ return this.altEl.val(this.alt);
+ }
+ };
+
+ return ImagePopover;
+
+})(Popover);
+
+Simditor.Toolbar.addButton(ImageButton);
+
+IndentButton = (function(superClass) {
+ extend(IndentButton, superClass);
+
+ function IndentButton() {
+ return IndentButton.__super__.constructor.apply(this, arguments);
+ }
+
+ IndentButton.prototype.name = 'indent';
+
+ IndentButton.prototype.icon = 'indent';
+
+ IndentButton.prototype._init = function() {
+ this.title = this._t(this.name) + ' (Tab)';
+ return IndentButton.__super__._init.call(this);
+ };
+
+ IndentButton.prototype._status = function() {};
+
+ IndentButton.prototype.command = function() {
+ return this.editor.indentation.indent();
+ };
+
+ return IndentButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(IndentButton);
+
+OutdentButton = (function(superClass) {
+ extend(OutdentButton, superClass);
+
+ function OutdentButton() {
+ return OutdentButton.__super__.constructor.apply(this, arguments);
+ }
+
+ OutdentButton.prototype.name = 'outdent';
+
+ OutdentButton.prototype.icon = 'outdent';
+
+ OutdentButton.prototype._init = function() {
+ this.title = this._t(this.name) + ' (Shift + Tab)';
+ return OutdentButton.__super__._init.call(this);
+ };
+
+ OutdentButton.prototype._status = function() {};
+
+ OutdentButton.prototype.command = function() {
+ return this.editor.indentation.indent(true);
+ };
+
+ return OutdentButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(OutdentButton);
+
+HrButton = (function(superClass) {
+ extend(HrButton, superClass);
+
+ function HrButton() {
+ return HrButton.__super__.constructor.apply(this, arguments);
+ }
+
+ HrButton.prototype.name = 'hr';
+
+ HrButton.prototype.icon = 'minus';
+
+ HrButton.prototype.htmlTag = 'hr';
+
+ HrButton.prototype._status = function() {};
+
+ HrButton.prototype.command = function() {
+ var $hr, $newBlock, $nextBlock, $rootBlock;
+ $rootBlock = this.editor.selection.rootNodes().first();
+ $nextBlock = $rootBlock.next();
+ if ($nextBlock.length > 0) {
+ this.editor.selection.save();
+ } else {
+ $newBlock = $('').append(this.editor.util.phBr);
+ }
+ $hr = $('
').insertAfter($rootBlock);
+ if ($newBlock) {
+ $newBlock.insertAfter($hr);
+ this.editor.selection.setRangeAtStartOf($newBlock);
+ } else {
+ this.editor.selection.restore();
+ }
+ return this.editor.trigger('valuechanged');
+ };
+
+ return HrButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(HrButton);
+
+TableButton = (function(superClass) {
+ extend(TableButton, superClass);
+
+ function TableButton() {
+ return TableButton.__super__.constructor.apply(this, arguments);
+ }
+
+ TableButton.prototype.name = 'table';
+
+ TableButton.prototype.icon = 'table';
+
+ TableButton.prototype.htmlTag = 'table';
+
+ TableButton.prototype.disableTag = 'pre, li, blockquote';
+
+ TableButton.prototype.menu = true;
+
+ TableButton.prototype._init = function() {
+ TableButton.__super__._init.call(this);
+ $.merge(this.editor.formatter._allowedTags, ['thead', 'th', 'tbody', 'tr', 'td', 'colgroup', 'col']);
+ $.extend(this.editor.formatter._allowedAttributes, {
+ td: ['rowspan', 'colspan'],
+ col: ['width']
+ });
+ $.extend(this.editor.formatter._allowedStyles, {
+ td: ['text-align'],
+ th: ['text-align']
+ });
+ this._initShortcuts();
+ this.editor.on('decorate', (function(_this) {
+ return function(e, $el) {
+ return $el.find('table').each(function(i, table) {
+ return _this.decorate($(table));
+ });
+ };
+ })(this));
+ this.editor.on('undecorate', (function(_this) {
+ return function(e, $el) {
+ return $el.find('table').each(function(i, table) {
+ return _this.undecorate($(table));
+ });
+ };
+ })(this));
+ this.editor.on('selectionchanged.table', (function(_this) {
+ return function(e) {
+ var $container, range;
+ _this.editor.body.find('.simditor-table td, .simditor-table th').removeClass('active');
+ range = _this.editor.selection.range();
+ if (!range) {
+ return;
+ }
+ $container = _this.editor.selection.containerNode();
+ if (range.collapsed && $container.is('.simditor-table')) {
+ if (_this.editor.selection.rangeAtStartOf($container)) {
+ $container = $container.find('th:first');
+ } else {
+ $container = $container.find('td:last');
+ }
+ _this.editor.selection.setRangeAtEndOf($container);
+ }
+ return $container.closest('td, th', _this.editor.body).addClass('active');
+ };
+ })(this));
+ this.editor.on('blur.table', (function(_this) {
+ return function(e) {
+ return _this.editor.body.find('.simditor-table td, .simditor-table th').removeClass('active');
+ };
+ })(this));
+ this.editor.keystroke.add('up', 'td', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'up');
+ return true;
+ };
+ })(this));
+ this.editor.keystroke.add('up', 'th', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'up');
+ return true;
+ };
+ })(this));
+ this.editor.keystroke.add('down', 'td', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'down');
+ return true;
+ };
+ })(this));
+ return this.editor.keystroke.add('down', 'th', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'down');
+ return true;
+ };
+ })(this));
+ };
+
+ TableButton.prototype._tdNav = function($td, direction) {
+ var $anotherTr, $tr, action, anotherTag, index, parentTag, ref;
+ if (direction == null) {
+ direction = 'up';
+ }
+ action = direction === 'up' ? 'prev' : 'next';
+ ref = direction === 'up' ? ['tbody', 'thead'] : ['thead', 'tbody'], parentTag = ref[0], anotherTag = ref[1];
+ $tr = $td.parent('tr');
+ $anotherTr = this["_" + action + "Row"]($tr);
+ if (!($anotherTr.length > 0)) {
+ return true;
+ }
+ index = $tr.find('td, th').index($td);
+ return this.editor.selection.setRangeAtEndOf($anotherTr.find('td, th').eq(index));
+ };
+
+ TableButton.prototype._nextRow = function($tr) {
+ var $nextTr;
+ $nextTr = $tr.next('tr');
+ if ($nextTr.length < 1 && $tr.parent('thead').length > 0) {
+ $nextTr = $tr.parent('thead').next('tbody').find('tr:first');
+ }
+ return $nextTr;
+ };
+
+ TableButton.prototype._prevRow = function($tr) {
+ var $prevTr;
+ $prevTr = $tr.prev('tr');
+ if ($prevTr.length < 1 && $tr.parent('tbody').length > 0) {
+ $prevTr = $tr.parent('tbody').prev('thead').find('tr');
+ }
+ return $prevTr;
+ };
+
+ TableButton.prototype.initResize = function($table) {
+ var $colgroup, $resizeHandle, $wrapper;
+ $wrapper = $table.parent('.simditor-table');
+ $colgroup = $table.find('colgroup');
+ if ($colgroup.length < 1) {
+ $colgroup = $('').prependTo($table);
+ $table.find('thead tr th').each(function(i, td) {
+ var $col;
+ return $col = $('').appendTo($colgroup);
+ });
+ this.refreshTableWidth($table);
+ }
+ $resizeHandle = $('', {
+ "class": 'simditor-resize-handle',
+ contenteditable: 'false'
+ }).appendTo($wrapper);
+ $wrapper.on('mousemove', 'td, th', function(e) {
+ var $col, $td, index, ref, ref1, x;
+ if ($wrapper.hasClass('resizing')) {
+ return;
+ }
+ $td = $(e.currentTarget);
+ x = e.pageX - $(e.currentTarget).offset().left;
+ if (x < 5 && $td.prev().length > 0) {
+ $td = $td.prev();
+ }
+ if ($td.next('td, th').length < 1) {
+ $resizeHandle.hide();
+ return;
+ }
+ if ((ref = $resizeHandle.data('td')) != null ? ref.is($td) : void 0) {
+ $resizeHandle.show();
+ return;
+ }
+ index = $td.parent().find('td, th').index($td);
+ $col = $colgroup.find('col').eq(index);
+ if ((ref1 = $resizeHandle.data('col')) != null ? ref1.is($col) : void 0) {
+ $resizeHandle.show();
+ return;
+ }
+ return $resizeHandle.css('left', $td.position().left + $td.outerWidth() - 5).data('td', $td).data('col', $col).show();
+ });
+ $wrapper.on('mouseleave', function(e) {
+ return $resizeHandle.hide();
+ });
+ return $wrapper.on('mousedown', '.simditor-resize-handle', function(e) {
+ var $handle, $leftCol, $leftTd, $rightCol, $rightTd, minWidth, startHandleLeft, startLeftWidth, startRightWidth, startX, tableWidth;
+ $handle = $(e.currentTarget);
+ $leftTd = $handle.data('td');
+ $leftCol = $handle.data('col');
+ $rightTd = $leftTd.next('td, th');
+ $rightCol = $leftCol.next('col');
+ startX = e.pageX;
+ startLeftWidth = $leftTd.outerWidth() * 1;
+ startRightWidth = $rightTd.outerWidth() * 1;
+ startHandleLeft = parseFloat($handle.css('left'));
+ tableWidth = $leftTd.closest('table').width();
+ minWidth = 50;
+ $(document).on('mousemove.simditor-resize-table', function(e) {
+ var deltaX, leftWidth, rightWidth;
+ deltaX = e.pageX - startX;
+ leftWidth = startLeftWidth + deltaX;
+ rightWidth = startRightWidth - deltaX;
+ if (leftWidth < minWidth) {
+ leftWidth = minWidth;
+ deltaX = minWidth - startLeftWidth;
+ rightWidth = startRightWidth - deltaX;
+ } else if (rightWidth < minWidth) {
+ rightWidth = minWidth;
+ deltaX = startRightWidth - minWidth;
+ leftWidth = startLeftWidth + deltaX;
+ }
+ $leftCol.attr('width', (leftWidth / tableWidth * 100) + '%');
+ $rightCol.attr('width', (rightWidth / tableWidth * 100) + '%');
+ return $handle.css('left', startHandleLeft + deltaX);
+ });
+ $(document).one('mouseup.simditor-resize-table', function(e) {
+ $(document).off('.simditor-resize-table');
+ return $wrapper.removeClass('resizing');
+ });
+ $wrapper.addClass('resizing');
+ return false;
+ });
+ };
+
+ TableButton.prototype._initShortcuts = function() {
+ this.editor.hotkeys.add('ctrl+alt+up', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertRowAbove]').click();
+ return false;
+ };
+ })(this));
+ this.editor.hotkeys.add('ctrl+alt+down', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertRowBelow]').click();
+ return false;
+ };
+ })(this));
+ this.editor.hotkeys.add('ctrl+alt+left', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertColLeft]').click();
+ return false;
+ };
+ })(this));
+ return this.editor.hotkeys.add('ctrl+alt+right', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertColRight]').click();
+ return false;
+ };
+ })(this));
+ };
+
+ TableButton.prototype.decorate = function($table) {
+ var $headRow, $tbody, $thead;
+ if ($table.parent('.simditor-table').length > 0) {
+ this.undecorate($table);
+ }
+ $table.wrap('');
+ if ($table.find('thead').length < 1) {
+ $thead = $('');
+ $headRow = $table.find('tr').first();
+ $thead.append($headRow);
+ this._changeCellTag($headRow, 'th');
+ $tbody = $table.find('tbody');
+ if ($tbody.length > 0) {
+ $tbody.before($thead);
+ } else {
+ $table.prepend($thead);
+ }
+ }
+ this.initResize($table);
+ return $table.parent();
+ };
+
+ TableButton.prototype.undecorate = function($table) {
+ if (!($table.parent('.simditor-table').length > 0)) {
+ return;
+ }
+ return $table.parent().replaceWith($table);
+ };
+
+ TableButton.prototype.renderMenu = function() {
+ var $table;
+ $("\n").appendTo(this.menuWrapper);
+ this.createMenu = this.menuWrapper.find('.menu-create-table');
+ this.editMenu = this.menuWrapper.find('.menu-edit-table');
+ $table = this.createTable(6, 6).appendTo(this.createMenu);
+ this.createMenu.on('mouseenter', 'td, th', (function(_this) {
+ return function(e) {
+ var $td, $tr, $trs, num;
+ _this.createMenu.find('td, th').removeClass('selected');
+ $td = $(e.currentTarget);
+ $tr = $td.parent();
+ num = $tr.find('td, th').index($td) + 1;
+ $trs = $tr.prevAll('tr').addBack();
+ if ($tr.parent().is('tbody')) {
+ $trs = $trs.add($table.find('thead tr'));
+ }
+ return $trs.find("td:lt(" + num + "), th:lt(" + num + ")").addClass('selected');
+ };
+ })(this));
+ this.createMenu.on('mouseleave', function(e) {
+ return $(e.currentTarget).find('td, th').removeClass('selected');
+ });
+ return this.createMenu.on('mousedown', 'td, th', (function(_this) {
+ return function(e) {
+ var $closestBlock, $td, $tr, colNum, rowNum;
+ _this.wrapper.removeClass('menu-on');
+ if (!_this.editor.inputManager.focused) {
+ return;
+ }
+ $td = $(e.currentTarget);
+ $tr = $td.parent();
+ colNum = $tr.find('td').index($td) + 1;
+ rowNum = $tr.prevAll('tr').length + 1;
+ if ($tr.parent().is('tbody')) {
+ rowNum += 1;
+ }
+ $table = _this.createTable(rowNum, colNum, true);
+ $closestBlock = _this.editor.selection.blockNodes().last();
+ if (_this.editor.util.isEmptyNode($closestBlock)) {
+ $closestBlock.replaceWith($table);
+ } else {
+ $closestBlock.after($table);
+ }
+ _this.decorate($table);
+ _this.editor.selection.setRangeAtStartOf($table.find('th:first'));
+ _this.editor.trigger('valuechanged');
+ return false;
+ };
+ })(this));
+ };
+
+ TableButton.prototype.createTable = function(row, col, phBr) {
+ var $table, $tbody, $td, $thead, $tr, c, k, l, r, ref, ref1;
+ $table = $('');
+ $thead = $('').appendTo($table);
+ $tbody = $('').appendTo($table);
+ for (r = k = 0, ref = row; 0 <= ref ? k < ref : k > ref; r = 0 <= ref ? ++k : --k) {
+ $tr = $('
');
+ $tr.appendTo(r === 0 ? $thead : $tbody);
+ for (c = l = 0, ref1 = col; 0 <= ref1 ? l < ref1 : l > ref1; c = 0 <= ref1 ? ++l : --l) {
+ $td = $(r === 0 ? ' | ' : ' | ').appendTo($tr);
+ if (phBr) {
+ $td.append(this.editor.util.phBr);
+ }
+ }
+ }
+ return $table;
+ };
+
+ TableButton.prototype.refreshTableWidth = function($table) {
+ var cols, tableWidth;
+ tableWidth = $table.width();
+ cols = $table.find('col');
+ return $table.find('thead tr th').each(function(i, td) {
+ var $col;
+ $col = cols.eq(i);
+ return $col.attr('width', ($(td).outerWidth() / tableWidth * 100) + '%');
+ });
+ };
+
+ TableButton.prototype.setActive = function(active) {
+ TableButton.__super__.setActive.call(this, active);
+ if (active) {
+ this.createMenu.hide();
+ return this.editMenu.show();
+ } else {
+ this.createMenu.show();
+ return this.editMenu.hide();
+ }
+ };
+
+ TableButton.prototype._changeCellTag = function($tr, tagName) {
+ return $tr.find('td, th').each(function(i, cell) {
+ var $cell;
+ $cell = $(cell);
+ return $cell.replaceWith("<" + tagName + ">" + ($cell.html()) + "" + tagName + ">");
+ });
+ };
+
+ TableButton.prototype.deleteRow = function($td) {
+ var $newTr, $tr, index;
+ $tr = $td.parent('tr');
+ if ($tr.closest('table').find('tr').length < 1) {
+ return this.deleteTable($td);
+ } else {
+ $newTr = this._nextRow($tr);
+ if (!($newTr.length > 0)) {
+ $newTr = this._prevRow($tr);
+ }
+ index = $tr.find('td, th').index($td);
+ if ($tr.parent().is('thead')) {
+ $newTr.appendTo($tr.parent());
+ this._changeCellTag($newTr, 'th');
+ }
+ $tr.remove();
+ return this.editor.selection.setRangeAtEndOf($newTr.find('td, th').eq(index));
+ }
+ };
+
+ TableButton.prototype.insertRow = function($td, direction) {
+ var $newTr, $table, $tr, cellTag, colNum, i, index, k, ref;
+ if (direction == null) {
+ direction = 'after';
+ }
+ $tr = $td.parent('tr');
+ $table = $tr.closest('table');
+ colNum = 0;
+ $table.find('tr').each(function(i, tr) {
+ return colNum = Math.max(colNum, $(tr).find('td').length);
+ });
+ index = $tr.find('td, th').index($td);
+ $newTr = $('
');
+ cellTag = 'td';
+ if (direction === 'after' && $tr.parent().is('thead')) {
+ $tr.parent().next('tbody').prepend($newTr);
+ } else if (direction === 'before' && $tr.parent().is('thead')) {
+ $tr.before($newTr);
+ $tr.parent().next('tbody').prepend($tr);
+ this._changeCellTag($tr, 'td');
+ cellTag = 'th';
+ } else {
+ $tr[direction]($newTr);
+ }
+ for (i = k = 1, ref = colNum; 1 <= ref ? k <= ref : k >= ref; i = 1 <= ref ? ++k : --k) {
+ $("<" + cellTag + "/>").append(this.editor.util.phBr).appendTo($newTr);
+ }
+ return this.editor.selection.setRangeAtStartOf($newTr.find('td, th').eq(index));
+ };
+
+ TableButton.prototype.deleteCol = function($td) {
+ var $newTd, $table, $tr, index, noOtherCol, noOtherRow;
+ $tr = $td.parent('tr');
+ noOtherRow = $tr.closest('table').find('tr').length < 2;
+ noOtherCol = $td.siblings('td, th').length < 1;
+ if (noOtherRow && noOtherCol) {
+ return this.deleteTable($td);
+ } else {
+ index = $tr.find('td, th').index($td);
+ $newTd = $td.next('td, th');
+ if (!($newTd.length > 0)) {
+ $newTd = $tr.prev('td, th');
+ }
+ $table = $tr.closest('table');
+ $table.find('col').eq(index).remove();
+ $table.find('tr').each(function(i, tr) {
+ return $(tr).find('td, th').eq(index).remove();
+ });
+ this.refreshTableWidth($table);
+ return this.editor.selection.setRangeAtEndOf($newTd);
+ }
+ };
+
+ TableButton.prototype.insertCol = function($td, direction) {
+ var $col, $newCol, $newTd, $table, $tr, index, tableWidth, width;
+ if (direction == null) {
+ direction = 'after';
+ }
+ $tr = $td.parent('tr');
+ index = $tr.find('td, th').index($td);
+ $table = $td.closest('table');
+ $col = $table.find('col').eq(index);
+ $table.find('tr').each((function(_this) {
+ return function(i, tr) {
+ var $newTd, cellTag;
+ cellTag = $(tr).parent().is('thead') ? 'th' : 'td';
+ $newTd = $("<" + cellTag + "/>").append(_this.editor.util.phBr);
+ return $(tr).find('td, th').eq(index)[direction]($newTd);
+ };
+ })(this));
+ $newCol = $('');
+ $col[direction]($newCol);
+ tableWidth = $table.width();
+ width = Math.max(parseFloat($col.attr('width')) / 2, 50 / tableWidth * 100);
+ $col.attr('width', width + '%');
+ $newCol.attr('width', width + '%');
+ this.refreshTableWidth($table);
+ $newTd = direction === 'after' ? $td.next('td, th') : $td.prev('td, th');
+ return this.editor.selection.setRangeAtStartOf($newTd);
+ };
+
+ TableButton.prototype.deleteTable = function($td) {
+ var $block, $table;
+ $table = $td.closest('.simditor-table');
+ $block = $table.next('p');
+ $table.remove();
+ if ($block.length > 0) {
+ return this.editor.selection.setRangeAtStartOf($block);
+ }
+ };
+
+ TableButton.prototype.command = function(param) {
+ var $td;
+ $td = this.editor.selection.containerNode().closest('td, th');
+ if (!($td.length > 0)) {
+ return;
+ }
+ if (param === 'deleteRow') {
+ this.deleteRow($td);
+ } else if (param === 'insertRowAbove') {
+ this.insertRow($td, 'before');
+ } else if (param === 'insertRowBelow') {
+ this.insertRow($td);
+ } else if (param === 'deleteCol') {
+ this.deleteCol($td);
+ } else if (param === 'insertColLeft') {
+ this.insertCol($td, 'before');
+ } else if (param === 'insertColRight') {
+ this.insertCol($td);
+ } else if (param === 'deleteTable') {
+ this.deleteTable($td);
+ } else {
+ return;
+ }
+ return this.editor.trigger('valuechanged');
+ };
+
+ return TableButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(TableButton);
+
+StrikethroughButton = (function(superClass) {
+ extend(StrikethroughButton, superClass);
+
+ function StrikethroughButton() {
+ return StrikethroughButton.__super__.constructor.apply(this, arguments);
+ }
+
+ StrikethroughButton.prototype.name = 'strikethrough';
+
+ StrikethroughButton.prototype.icon = 'strikethrough';
+
+ StrikethroughButton.prototype.htmlTag = 'strike';
+
+ StrikethroughButton.prototype.disableTag = 'pre';
+
+ StrikethroughButton.prototype._activeStatus = function() {
+ var active;
+ active = document.queryCommandState('strikethrough') === true;
+ this.setActive(active);
+ return this.active;
+ };
+
+ StrikethroughButton.prototype.command = function() {
+ document.execCommand('strikethrough');
+ if (!this.editor.util.support.oninput) {
+ this.editor.trigger('valuechanged');
+ }
+ return $(document).trigger('selectionchange');
+ };
+
+ return StrikethroughButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(StrikethroughButton);
+
+AlignmentButton = (function(superClass) {
+ extend(AlignmentButton, superClass);
+
+ function AlignmentButton() {
+ return AlignmentButton.__super__.constructor.apply(this, arguments);
+ }
+
+ AlignmentButton.prototype.name = "alignment";
+
+ AlignmentButton.prototype.icon = 'align-left';
+
+ AlignmentButton.prototype.htmlTag = 'p, h1, h2, h3, h4, td, th';
+
+ AlignmentButton.prototype._init = function() {
+ this.menu = [
+ {
+ name: 'left',
+ text: this._t('alignLeft'),
+ icon: 'align-left',
+ param: 'left'
+ }, {
+ name: 'center',
+ text: this._t('alignCenter'),
+ icon: 'align-center',
+ param: 'center'
+ }, {
+ name: 'right',
+ text: this._t('alignRight'),
+ icon: 'align-right',
+ param: 'right'
+ }
+ ];
+ return AlignmentButton.__super__._init.call(this);
+ };
+
+ AlignmentButton.prototype.setActive = function(active, align) {
+ if (align == null) {
+ align = 'left';
+ }
+ if (align !== 'left' && align !== 'center' && align !== 'right') {
+ align = 'left';
+ }
+ if (align === 'left') {
+ AlignmentButton.__super__.setActive.call(this, false);
+ } else {
+ AlignmentButton.__super__.setActive.call(this, active);
+ }
+ this.el.removeClass('align-left align-center align-right');
+ if (active) {
+ this.el.addClass('align-' + align);
+ }
+ this.setIcon('align-' + align);
+ return this.menuEl.find('.menu-item').show().end().find('.menu-item-' + align).hide();
+ };
+
+ AlignmentButton.prototype._status = function() {
+ this.nodes = this.editor.selection.nodes().filter(this.htmlTag);
+ if (this.nodes.length < 1) {
+ this.setDisabled(true);
+ return this.setActive(false);
+ } else {
+ this.setDisabled(false);
+ return this.setActive(true, this.nodes.first().css('text-align'));
+ }
+ };
+
+ AlignmentButton.prototype.command = function(align) {
+ if (align !== 'left' && align !== 'center' && align !== 'right') {
+ throw new Error("simditor alignment button: invalid align " + align);
+ }
+ this.nodes.css({
+ 'text-align': align === 'left' ? '' : align
+ });
+ this.editor.trigger('valuechanged');
+ return this.editor.inputManager.throttledSelectionChanged();
+ };
+
+ return AlignmentButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(AlignmentButton);
+
+return Simditor;
+
+}));
diff --git a/public/js/uploader.js b/public/js/uploader.js
new file mode 100644
index 000000000..d96860ec0
--- /dev/null
+++ b/public/js/uploader.js
@@ -0,0 +1,261 @@
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module unless amdModuleId is set
+ define('simple-uploader', ["jquery","simple-module"], function ($, SimpleModule) {
+ return (root['uploader'] = 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['uploader'] = factory(jQuery,SimpleModule);
+ }
+}(this, function ($, SimpleModule) {
+
+var Uploader, uploader,
+ 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;
+
+Uploader = (function(superClass) {
+ extend(Uploader, superClass);
+
+ function Uploader() {
+ return Uploader.__super__.constructor.apply(this, arguments);
+ }
+
+ Uploader.count = 0;
+
+ Uploader.prototype.opts = {
+ url: '',
+ params: null,
+ fileKey: 'upload_file',
+ connectionCount: 3
+ };
+
+ Uploader.prototype._init = function() {
+ this.files = [];
+ this.queue = [];
+ this.id = ++Uploader.count;
+ this.on('uploadcomplete', (function(_this) {
+ return function(e, file) {
+ _this.files.splice($.inArray(file, _this.files), 1);
+ if (_this.queue.length > 0 && _this.files.length < _this.opts.connectionCount) {
+ return _this.upload(_this.queue.shift());
+ } else {
+ return _this.uploading = false;
+ }
+ };
+ })(this));
+ return $(window).on('beforeunload.uploader-' + this.id, (function(_this) {
+ return function(e) {
+ if (!_this.uploading) {
+ return;
+ }
+ e.originalEvent.returnValue = _this._t('leaveConfirm');
+ return _this._t('leaveConfirm');
+ };
+ })(this));
+ };
+
+ Uploader.prototype.generateId = (function() {
+ var id;
+ id = 0;
+ return function() {
+ return id += 1;
+ };
+ })();
+
+ Uploader.prototype.upload = function(file, opts) {
+ var f, i, key, len;
+ if (opts == null) {
+ opts = {};
+ }
+ if (file == null) {
+ return;
+ }
+ if ($.isArray(file) || file instanceof FileList) {
+ for (i = 0, len = file.length; i < len; i++) {
+ f = file[i];
+ this.upload(f, opts);
+ }
+ } else if ($(file).is('input:file')) {
+ key = $(file).attr('name');
+ if (key) {
+ opts.fileKey = key;
+ }
+ this.upload($.makeArray($(file)[0].files), opts);
+ } else if (!file.id || !file.obj) {
+ file = this.getFile(file);
+ }
+ if (!(file && file.obj)) {
+ return;
+ }
+ $.extend(file, opts);
+ if (this.files.length >= this.opts.connectionCount) {
+ this.queue.push(file);
+ return;
+ }
+ if (this.triggerHandler('beforeupload', [file]) === false) {
+ return;
+ }
+ this.files.push(file);
+ this._xhrUpload(file);
+ return this.uploading = true;
+ };
+
+ Uploader.prototype.getFile = function(fileObj) {
+ var name, ref, ref1;
+ if (fileObj instanceof window.File || fileObj instanceof window.Blob) {
+ name = (ref = fileObj.fileName) != null ? ref : fileObj.name;
+ } else {
+ return null;
+ }
+ return {
+ id: this.generateId(),
+ url: this.opts.url,
+ params: this.opts.params,
+ fileKey: this.opts.fileKey,
+ name: name,
+ size: (ref1 = fileObj.fileSize) != null ? ref1 : fileObj.size,
+ ext: name ? name.split('.').pop().toLowerCase() : '',
+ obj: fileObj
+ };
+ };
+
+ Uploader.prototype._xhrUpload = function(file) {
+ var formData, k, ref, v;
+ formData = new FormData();
+ formData.append(file.fileKey, file.obj);
+ formData.append("original_filename", file.name);
+ if (file.params) {
+ ref = file.params;
+ for (k in ref) {
+ v = ref[k];
+ formData.append(k, v);
+ }
+ }
+ return file.xhr = $.ajax({
+ url: file.url,
+ data: formData,
+ processData: false,
+ contentType: false,
+ type: 'POST',
+ headers: {
+ 'X-File-Name': encodeURIComponent(file.name)
+ },
+ xhr: function() {
+ var req;
+ req = $.ajaxSettings.xhr();
+ if (req) {
+ req.upload.onprogress = (function(_this) {
+ return function(e) {
+ return _this.progress(e);
+ };
+ })(this);
+ }
+ return req;
+ },
+ progress: (function(_this) {
+ return function(e) {
+ if (!e.lengthComputable) {
+ return;
+ }
+ return _this.trigger('uploadprogress', [file, e.loaded, e.total]);
+ };
+ })(this),
+ error: (function(_this) {
+ return function(xhr, status, err) {
+ return _this.trigger('uploaderror', [file, xhr, status]);
+ };
+ })(this),
+ success: (function(_this) {
+ return function(result) {
+ _this.trigger('uploadprogress', [file, file.size, file.size]);
+ _this.trigger('uploadsuccess', [file, result]);
+ return $(document).trigger('uploadsuccess', [file, result, _this]);
+ };
+ })(this),
+ complete: (function(_this) {
+ return function(xhr, status) {
+ return _this.trigger('uploadcomplete', [file, xhr.responseText]);
+ };
+ })(this)
+ });
+ };
+
+ Uploader.prototype.cancel = function(file) {
+ var f, i, len, ref;
+ if (!file.id) {
+ ref = this.files;
+ for (i = 0, len = ref.length; i < len; i++) {
+ f = ref[i];
+ if (f.id === file * 1) {
+ file = f;
+ break;
+ }
+ }
+ }
+ this.trigger('uploadcancel', [file]);
+ if (file.xhr) {
+ file.xhr.abort();
+ }
+ return file.xhr = null;
+ };
+
+ Uploader.prototype.readImageFile = function(fileObj, callback) {
+ var fileReader, img;
+ if (!$.isFunction(callback)) {
+ return;
+ }
+ img = new Image();
+ img.onload = function() {
+ return callback(img);
+ };
+ img.onerror = function() {
+ return callback();
+ };
+ if (window.FileReader && FileReader.prototype.readAsDataURL && /^image/.test(fileObj.type)) {
+ fileReader = new FileReader();
+ fileReader.onload = function(e) {
+ return img.src = e.target.result;
+ };
+ return fileReader.readAsDataURL(fileObj);
+ } else {
+ return callback();
+ }
+ };
+
+ Uploader.prototype.destroy = function() {
+ var file, i, len, ref;
+ this.queue.length = 0;
+ ref = this.files;
+ for (i = 0, len = ref.length; i < len; i++) {
+ file = ref[i];
+ this.cancel(file);
+ }
+ $(window).off('.uploader-' + this.id);
+ return $(document).off('.uploader-' + this.id);
+ };
+
+ Uploader.i18n = {
+ 'zh-CN': {
+ leaveConfirm: '正在上传文件,如果离开上传会自动取消'
+ }
+ };
+
+ Uploader.locale = 'zh-CN';
+
+ return Uploader;
+
+})(SimpleModule);
+
+uploader = function(opts) {
+ return new Uploader(opts);
+};
+
+return uploader;
+
+}));
diff --git a/resources/.DS_Store b/resources/.DS_Store
new file mode 100644
index 000000000..ff70508e1
Binary files /dev/null and b/resources/.DS_Store differ
diff --git a/resources/editor/.DS_Store b/resources/editor/.DS_Store
new file mode 100644
index 000000000..6c07eda65
Binary files /dev/null and b/resources/editor/.DS_Store differ
diff --git a/resources/editor/css/.DS_Store b/resources/editor/css/.DS_Store
new file mode 100644
index 000000000..5008ddfcf
Binary files /dev/null and b/resources/editor/css/.DS_Store differ
diff --git a/resources/editor/css/simditor.css b/resources/editor/css/simditor.css
new file mode 100644
index 000000000..341ae827d
--- /dev/null
+++ b/resources/editor/css/simditor.css
@@ -0,0 +1,746 @@
+/*!
+* Simditor v2.3.6
+* http://simditor.tower.im/
+* 2015-12-21
+*/
+@font-face {
+ font-family: 'Simditor';
+ src: url(data:application/font-woff;charset=utf-8;base64,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) format("woff");
+ font-weight: normal;
+ font-style: normal;
+}
+.simditor-icon {
+ display: inline-block;
+ font: normal normal normal 14px/1 'Simditor';
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ transform: translate(0, 0);
+}
+
+.simditor-icon-code:before {
+ content: '\f000';
+}
+
+.simditor-icon-bold:before {
+ content: '\f001';
+}
+
+.simditor-icon-italic:before {
+ content: '\f002';
+}
+
+.simditor-icon-underline:before {
+ content: '\f003';
+}
+
+.simditor-icon-times:before {
+ content: '\f004';
+}
+
+.simditor-icon-strikethrough:before {
+ content: '\f005';
+}
+
+.simditor-icon-list-ol:before {
+ content: '\f006';
+}
+
+.simditor-icon-list-ul:before {
+ content: '\f007';
+}
+
+.simditor-icon-quote-left:before {
+ content: '\f008';
+}
+
+.simditor-icon-table:before {
+ content: '\f009';
+}
+
+.simditor-icon-link:before {
+ content: '\f00a';
+}
+
+.simditor-icon-picture-o:before {
+ content: '\f00b';
+}
+
+.simditor-icon-minus:before {
+ content: '\f00c';
+}
+
+.simditor-icon-indent:before {
+ content: '\f00d';
+}
+
+.simditor-icon-outdent:before {
+ content: '\f00e';
+}
+
+.simditor-icon-unlink:before {
+ content: '\f00f';
+}
+
+.simditor-icon-caret-down:before {
+ content: '\f010';
+}
+
+.simditor-icon-caret-right:before {
+ content: '\f011';
+}
+
+.simditor-icon-upload:before {
+ content: '\f012';
+}
+
+.simditor-icon-undo:before {
+ content: '\f013';
+}
+
+.simditor-icon-smile-o:before {
+ content: '\f014';
+}
+
+.simditor-icon-tint:before {
+ content: '\f015';
+}
+
+.simditor-icon-font:before {
+ content: '\f016';
+}
+
+.simditor-icon-html5:before {
+ content: '\f017';
+}
+
+.simditor-icon-mark:before {
+ content: '\f018';
+}
+
+.simditor-icon-align-center:before {
+ content: '\f019';
+}
+
+.simditor-icon-align-left:before {
+ content: '\f01a';
+}
+
+.simditor-icon-align-right:before {
+ content: '\f01b';
+}
+
+.simditor-icon-font-minus:before {
+ content: '\f01c';
+}
+
+.simditor-icon-markdown:before {
+ content: '\f01d';
+}
+
+.simditor-icon-checklist:before {
+ content: '\f01e';
+}
+
+.simditor {
+ position: relative;
+ border: 1px solid #c9d8db;
+}
+.simditor .simditor-wrapper {
+ position: relative;
+ background: #ffffff;
+}
+.simditor .simditor-wrapper > 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/resources/editor/js/hotkeys.js b/resources/editor/js/hotkeys.js
new file mode 100644
index 000000000..de20b918c
--- /dev/null
+++ b/resources/editor/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/resources/editor/js/module.js b/resources/editor/js/module.js
new file mode 100644
index 000000000..9f7dbbd7c
--- /dev/null
+++ b/resources/editor/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/resources/editor/js/simditor.js b/resources/editor/js/simditor.js
new file mode 100644
index 000000000..056090fbb
--- /dev/null
+++ b/resources/editor/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 = "";
+
+ 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 + ">" + _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 = $('', {
+ text: lang.name,
+ value: lang.value
+ }).appendTo(this.selectEl);
+ }
+ this.selectEl.on('change', (function(_this) {
+ return function(e) {
+ var selected;
+ _this.lang = _this.selectEl.val();
+ selected = _this.target.hasClass('selected');
+ _this.target.removeClass().removeAttr('data-lang');
+ if (_this.lang !== -1) {
+ _this.target.attr('data-lang', _this.lang);
+ }
+ if (selected) {
+ _this.target.addClass('selected');
+ }
+ return _this.editor.trigger('valuechanged');
+ };
+ })(this));
+ return this.editor.on('valuechanged', (function(_this) {
+ return function(e) {
+ if (_this.active) {
+ return _this.refresh();
+ }
+ };
+ })(this));
+ };
+
+ CodePopover.prototype.show = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ CodePopover.__super__.show.apply(this, args);
+ this.lang = this.target.attr('data-lang');
+ if (this.lang != null) {
+ return this.selectEl.val(this.lang);
+ } else {
+ return this.selectEl.val(-1);
+ }
+ };
+
+ return CodePopover;
+
+})(Popover);
+
+Simditor.Toolbar.addButton(CodeButton);
+
+LinkButton = (function(superClass) {
+ extend(LinkButton, superClass);
+
+ function LinkButton() {
+ return LinkButton.__super__.constructor.apply(this, arguments);
+ }
+
+ LinkButton.prototype.name = 'link';
+
+ LinkButton.prototype.icon = 'link';
+
+ LinkButton.prototype.htmlTag = 'a';
+
+ LinkButton.prototype.disableTag = 'pre';
+
+ LinkButton.prototype.render = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ LinkButton.__super__.render.apply(this, args);
+ return this.popover = new LinkPopover({
+ button: this
+ });
+ };
+
+ LinkButton.prototype._status = function() {
+ LinkButton.__super__._status.call(this);
+ if (this.active && !this.editor.selection.rangeAtEndOf(this.node)) {
+ return this.popover.show(this.node);
+ } else {
+ return this.popover.hide();
+ }
+ };
+
+ LinkButton.prototype.command = function() {
+ var $contents, $link, $newBlock, linkText, range, txtNode;
+ range = this.editor.selection.range();
+ if (this.active) {
+ txtNode = document.createTextNode(this.node.text());
+ this.node.replaceWith(txtNode);
+ range.selectNode(txtNode);
+ } else {
+ $contents = $(range.extractContents());
+ linkText = this.editor.formatter.clearHtml($contents.contents(), false);
+ $link = $('', {
+ href: 'http://www.example.com',
+ target: '_blank',
+ text: linkText || this._t('linkText')
+ });
+ if (this.editor.selection.blockNodes().length > 0) {
+ range.insertNode($link[0]);
+ } else {
+ $newBlock = $('').append($link);
+ range.insertNode($newBlock[0]);
+ }
+ range.selectNodeContents($link[0]);
+ this.popover.one('popovershow', (function(_this) {
+ return function() {
+ if (linkText) {
+ _this.popover.urlEl.focus();
+ return _this.popover.urlEl[0].select();
+ } else {
+ _this.popover.textEl.focus();
+ return _this.popover.textEl[0].select();
+ }
+ };
+ })(this));
+ }
+ this.editor.selection.range(range);
+ return this.editor.trigger('valuechanged');
+ };
+
+ return LinkButton;
+
+})(Button);
+
+LinkPopover = (function(superClass) {
+ extend(LinkPopover, superClass);
+
+ function LinkPopover() {
+ return LinkPopover.__super__.constructor.apply(this, arguments);
+ }
+
+ LinkPopover.prototype.render = function() {
+ var tpl;
+ tpl = "\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
";
+ this.el.addClass('link-popover').append(tpl);
+ this.textEl = this.el.find('.link-text');
+ this.urlEl = this.el.find('.link-url');
+ this.unlinkEl = this.el.find('.btn-unlink');
+ this.selectTarget = this.el.find('.link-target');
+ this.textEl.on('keyup', (function(_this) {
+ return function(e) {
+ if (e.which === 13) {
+ return;
+ }
+ _this.target.text(_this.textEl.val());
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ this.urlEl.on('keyup', (function(_this) {
+ return function(e) {
+ var val;
+ if (e.which === 13) {
+ return;
+ }
+ val = _this.urlEl.val();
+ if (!(/https?:\/\/|^\//ig.test(val) || !val)) {
+ val = 'http://' + val;
+ }
+ _this.target.attr('href', val);
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ $([this.urlEl[0], this.textEl[0]]).on('keydown', (function(_this) {
+ return function(e) {
+ var range;
+ if (e.which === 13 || e.which === 27 || (!e.shiftKey && e.which === 9 && $(e.target).hasClass('link-url'))) {
+ e.preventDefault();
+ range = document.createRange();
+ _this.editor.selection.setRangeAfter(_this.target, range);
+ _this.hide();
+ return _this.editor.inputManager.throttledValueChanged();
+ }
+ };
+ })(this));
+ this.unlinkEl.on('click', (function(_this) {
+ return function(e) {
+ var range, txtNode;
+ txtNode = document.createTextNode(_this.target.text());
+ _this.target.replaceWith(txtNode);
+ _this.hide();
+ range = document.createRange();
+ _this.editor.selection.setRangeAfter(txtNode, range);
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ return this.selectTarget.on('change', (function(_this) {
+ return function(e) {
+ _this.target.attr('target', _this.selectTarget.val());
+ return _this.editor.inputManager.throttledValueChanged();
+ };
+ })(this));
+ };
+
+ LinkPopover.prototype.show = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ LinkPopover.__super__.show.apply(this, args);
+ this.textEl.val(this.target.text());
+ return this.urlEl.val(this.target.attr('href'));
+ };
+
+ return LinkPopover;
+
+})(Popover);
+
+Simditor.Toolbar.addButton(LinkButton);
+
+ImageButton = (function(superClass) {
+ extend(ImageButton, superClass);
+
+ function ImageButton() {
+ return ImageButton.__super__.constructor.apply(this, arguments);
+ }
+
+ ImageButton.prototype.name = 'image';
+
+ ImageButton.prototype.icon = 'picture-o';
+
+ ImageButton.prototype.htmlTag = 'img';
+
+ ImageButton.prototype.disableTag = 'pre, table';
+
+ ImageButton.prototype.defaultImage = '';
+
+ ImageButton.prototype.needFocus = false;
+
+ ImageButton.prototype._init = function() {
+ var item, k, len, ref;
+ if (this.editor.opts.imageButton) {
+ if (Array.isArray(this.editor.opts.imageButton)) {
+ this.menu = [];
+ ref = this.editor.opts.imageButton;
+ for (k = 0, len = ref.length; k < len; k++) {
+ item = ref[k];
+ this.menu.push({
+ name: item + '-image',
+ text: this._t(item + 'Image')
+ });
+ }
+ } else {
+ this.menu = false;
+ }
+ } else {
+ if (this.editor.uploader != null) {
+ this.menu = [
+ {
+ name: 'upload-image',
+ text: this._t('uploadImage')
+ }, {
+ name: 'external-image',
+ text: this._t('externalImage')
+ }
+ ];
+ } else {
+ this.menu = false;
+ }
+ }
+ this.defaultImage = this.editor.opts.defaultImage;
+ this.editor.body.on('click', 'img:not([data-non-image])', (function(_this) {
+ return function(e) {
+ var $img, range;
+ $img = $(e.currentTarget);
+ range = document.createRange();
+ range.selectNode($img[0]);
+ _this.editor.selection.range(range);
+ if (!_this.editor.util.support.onselectionchange) {
+ _this.editor.trigger('selectionchanged');
+ }
+ return false;
+ };
+ })(this));
+ this.editor.body.on('mouseup', 'img:not([data-non-image])', function(e) {
+ return false;
+ });
+ this.editor.on('selectionchanged.image', (function(_this) {
+ return function() {
+ var $contents, $img, range;
+ range = _this.editor.selection.range();
+ if (range == null) {
+ return;
+ }
+ $contents = $(range.cloneContents()).contents();
+ if ($contents.length === 1 && $contents.is('img:not([data-non-image])')) {
+ $img = $(range.startContainer).contents().eq(range.startOffset);
+ return _this.popover.show($img);
+ } else {
+ return _this.popover.hide();
+ }
+ };
+ })(this));
+ this.editor.on('valuechanged.image', (function(_this) {
+ return function() {
+ var $masks;
+ $masks = _this.editor.wrapper.find('.simditor-image-loading');
+ if (!($masks.length > 0)) {
+ return;
+ }
+ return $masks.each(function(i, mask) {
+ var $img, $mask, file;
+ $mask = $(mask);
+ $img = $mask.data('img');
+ if (!($img && $img.parent().length > 0)) {
+ $mask.remove();
+ if ($img) {
+ file = $img.data('file');
+ if (file) {
+ _this.editor.uploader.cancel(file);
+ if (_this.editor.body.find('img.uploading').length < 1) {
+ return _this.editor.uploader.trigger('uploadready', [file]);
+ }
+ }
+ }
+ }
+ });
+ };
+ })(this));
+ return ImageButton.__super__._init.call(this);
+ };
+
+ ImageButton.prototype.render = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ ImageButton.__super__.render.apply(this, args);
+ this.popover = new ImagePopover({
+ button: this
+ });
+ if (this.editor.opts.imageButton === 'upload') {
+ return this._initUploader(this.el);
+ }
+ };
+
+ ImageButton.prototype.renderMenu = function() {
+ ImageButton.__super__.renderMenu.call(this);
+ return this._initUploader();
+ };
+
+ ImageButton.prototype._initUploader = function($uploadItem) {
+ var $input, createInput, uploadProgress;
+ if ($uploadItem == null) {
+ $uploadItem = this.menuEl.find('.menu-item-upload-image');
+ }
+ if (this.editor.uploader == null) {
+ this.el.find('.btn-upload').remove();
+ return;
+ }
+ $input = null;
+ createInput = (function(_this) {
+ return function() {
+ if ($input) {
+ $input.remove();
+ }
+ return $input = $('', {
+ type: 'file',
+ title: _this._t('uploadImage'),
+ multiple: true,
+ accept: 'image/*'
+ }).appendTo($uploadItem);
+ };
+ })(this);
+ createInput();
+ $uploadItem.on('click mousedown', 'input[type=file]', function(e) {
+ return e.stopPropagation();
+ });
+ $uploadItem.on('change', 'input[type=file]', (function(_this) {
+ return function(e) {
+ if (_this.editor.inputManager.focused) {
+ _this.editor.uploader.upload($input, {
+ inline: true
+ });
+ createInput();
+ } else {
+ _this.editor.one('focus', function(e) {
+ _this.editor.uploader.upload($input, {
+ inline: true
+ });
+ return createInput();
+ });
+ _this.editor.focus();
+ }
+ return _this.wrapper.removeClass('menu-on');
+ };
+ })(this));
+ this.editor.uploader.on('beforeupload', (function(_this) {
+ return function(e, file) {
+ var $img;
+ if (!file.inline) {
+ return;
+ }
+ if (file.img) {
+ $img = $(file.img);
+ } else {
+ $img = _this.createImage(file.name);
+ file.img = $img;
+ }
+ $img.addClass('uploading');
+ $img.data('file', file);
+ return _this.editor.uploader.readImageFile(file.obj, function(img) {
+ var src;
+ if (!$img.hasClass('uploading')) {
+ return;
+ }
+ src = img ? img.src : _this.defaultImage;
+ return _this.loadImage($img, src, function() {
+ if (_this.popover.active) {
+ _this.popover.refresh();
+ return _this.popover.srcEl.val(_this._t('uploading')).prop('disabled', true);
+ }
+ });
+ });
+ };
+ })(this));
+ uploadProgress = $.proxy(this.editor.util.throttle(function(e, file, loaded, total) {
+ var $img, $mask, percent;
+ if (!file.inline) {
+ return;
+ }
+ $mask = file.img.data('mask');
+ if (!$mask) {
+ return;
+ }
+ $img = $mask.data('img');
+ if (!($img.hasClass('uploading') && $img.parent().length > 0)) {
+ $mask.remove();
+ return;
+ }
+ percent = loaded / total;
+ percent = (percent * 100).toFixed(0);
+ if (percent > 99) {
+ percent = 99;
+ }
+ return $mask.find('.progress').height((100 - percent) + "%");
+ }, 500), this);
+ this.editor.uploader.on('uploadprogress', uploadProgress);
+ this.editor.uploader.on('uploadsuccess', (function(_this) {
+ return function(e, file, result) {
+ var $img, img_path, msg;
+ if (!file.inline) {
+ return;
+ }
+ $img = file.img;
+ if (!($img.hasClass('uploading') && $img.parent().length > 0)) {
+ return;
+ }
+ if (typeof result !== 'object') {
+ try {
+ result = $.parseJSON(result);
+ } catch (_error) {
+ e = _error;
+ result = {
+ success: false
+ };
+ }
+ }
+ if (result.success === false) {
+ msg = result.msg || _this._t('uploadFailed');
+ alert(msg);
+ img_path = _this.defaultImage;
+ } else {
+ img_path = result.file_path;
+ }
+ _this.loadImage($img, img_path, function() {
+ var $mask;
+ $img.removeData('file');
+ $img.removeClass('uploading').removeClass('loading');
+ $mask = $img.data('mask');
+ if ($mask) {
+ $mask.remove();
+ }
+ $img.removeData('mask');
+ _this.editor.trigger('valuechanged');
+ if (_this.editor.body.find('img.uploading').length < 1) {
+ return _this.editor.uploader.trigger('uploadready', [file, result]);
+ }
+ });
+ if (_this.popover.active) {
+ _this.popover.srcEl.prop('disabled', false);
+ return _this.popover.srcEl.val(result.file_path);
+ }
+ };
+ })(this));
+ return this.editor.uploader.on('uploaderror', (function(_this) {
+ return function(e, file, xhr) {
+ var $img, msg, result;
+ if (!file.inline) {
+ return;
+ }
+ if (xhr.statusText === 'abort') {
+ return;
+ }
+ if (xhr.responseText) {
+ try {
+ result = $.parseJSON(xhr.responseText);
+ msg = result.msg;
+ } catch (_error) {
+ e = _error;
+ msg = _this._t('uploadError');
+ }
+ alert(msg);
+ }
+ $img = file.img;
+ if (!($img.hasClass('uploading') && $img.parent().length > 0)) {
+ return;
+ }
+ _this.loadImage($img, _this.defaultImage, function() {
+ var $mask;
+ $img.removeData('file');
+ $img.removeClass('uploading').removeClass('loading');
+ $mask = $img.data('mask');
+ if ($mask) {
+ $mask.remove();
+ }
+ return $img.removeData('mask');
+ });
+ if (_this.popover.active) {
+ _this.popover.srcEl.prop('disabled', false);
+ _this.popover.srcEl.val(_this.defaultImage);
+ }
+ _this.editor.trigger('valuechanged');
+ if (_this.editor.body.find('img.uploading').length < 1) {
+ return _this.editor.uploader.trigger('uploadready', [file, result]);
+ }
+ };
+ })(this));
+ };
+
+ ImageButton.prototype._status = function() {
+ return this._disableStatus();
+ };
+
+ ImageButton.prototype.loadImage = function($img, src, callback) {
+ var $mask, img, positionMask;
+ positionMask = (function(_this) {
+ return function() {
+ var imgOffset, wrapperOffset;
+ imgOffset = $img.offset();
+ wrapperOffset = _this.editor.wrapper.offset();
+ return $mask.css({
+ top: imgOffset.top - wrapperOffset.top,
+ left: imgOffset.left - wrapperOffset.left,
+ width: $img.width(),
+ height: $img.height()
+ }).show();
+ };
+ })(this);
+ $img.addClass('loading');
+ $mask = $img.data('mask');
+ if (!$mask) {
+ $mask = $('').hide().appendTo(this.editor.wrapper);
+ positionMask();
+ $img.data('mask', $mask);
+ $mask.data('img', $img);
+ }
+ img = new Image();
+ img.onload = (function(_this) {
+ return function() {
+ var height, width;
+ if (!$img.hasClass('loading') && !$img.hasClass('uploading')) {
+ return;
+ }
+ width = img.width;
+ height = img.height;
+ $img.attr({
+ src: src,
+ width: width,
+ height: height,
+ 'data-image-size': width + ',' + height
+ }).removeClass('loading');
+ if ($img.hasClass('uploading')) {
+ _this.editor.util.reflow(_this.editor.body);
+ positionMask();
+ } else {
+ $mask.remove();
+ $img.removeData('mask');
+ }
+ if ($.isFunction(callback)) {
+ return callback(img);
+ }
+ };
+ })(this);
+ img.onerror = function() {
+ if ($.isFunction(callback)) {
+ callback(false);
+ }
+ $mask.remove();
+ return $img.removeData('mask').removeClass('loading');
+ };
+ return img.src = src;
+ };
+
+ ImageButton.prototype.createImage = function(name) {
+ var $img, range;
+ if (name == null) {
+ name = 'Image';
+ }
+ if (!this.editor.inputManager.focused) {
+ this.editor.focus();
+ }
+ range = this.editor.selection.range();
+ range.deleteContents();
+ this.editor.selection.range(range);
+ $img = $('
').attr('alt', name);
+ range.insertNode($img[0]);
+ this.editor.selection.setRangeAfter($img, range);
+ this.editor.trigger('valuechanged');
+ return $img;
+ };
+
+ ImageButton.prototype.command = function(src) {
+ var $img;
+ $img = this.createImage();
+ return this.loadImage($img, src || this.defaultImage, (function(_this) {
+ return function() {
+ _this.editor.trigger('valuechanged');
+ _this.editor.util.reflow($img);
+ $img.click();
+ return _this.popover.one('popovershow', function() {
+ _this.popover.srcEl.focus();
+ return _this.popover.srcEl[0].select();
+ });
+ };
+ })(this));
+ };
+
+ return ImageButton;
+
+})(Button);
+
+ImagePopover = (function(superClass) {
+ extend(ImagePopover, superClass);
+
+ function ImagePopover() {
+ return ImagePopover.__super__.constructor.apply(this, arguments);
+ }
+
+ ImagePopover.prototype.offset = {
+ top: 6,
+ left: -4
+ };
+
+ ImagePopover.prototype.render = function() {
+ var tpl;
+ tpl = "\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n
\n
×\n
\n
\n \n \n
\n
";
+ this.el.addClass('image-popover').append(tpl);
+ this.srcEl = this.el.find('.image-src');
+ this.widthEl = this.el.find('#image-width');
+ this.heightEl = this.el.find('#image-height');
+ this.altEl = this.el.find('#image-alt');
+ this.srcEl.on('keydown', (function(_this) {
+ return function(e) {
+ var range;
+ if (!(e.which === 13 && !_this.target.hasClass('uploading'))) {
+ return;
+ }
+ e.preventDefault();
+ range = document.createRange();
+ _this.button.editor.selection.setRangeAfter(_this.target, range);
+ return _this.hide();
+ };
+ })(this));
+ this.srcEl.on('blur', (function(_this) {
+ return function(e) {
+ return _this._loadImage(_this.srcEl.val());
+ };
+ })(this));
+ this.el.find('.image-size').on('blur', (function(_this) {
+ return function(e) {
+ _this._resizeImg($(e.currentTarget));
+ return _this.el.data('popover').refresh();
+ };
+ })(this));
+ this.el.find('.image-size').on('keyup', (function(_this) {
+ return function(e) {
+ var inputEl;
+ inputEl = $(e.currentTarget);
+ if (!(e.which === 13 || e.which === 27 || e.which === 9)) {
+ return _this._resizeImg(inputEl, true);
+ }
+ };
+ })(this));
+ this.el.find('.image-size').on('keydown', (function(_this) {
+ return function(e) {
+ var $img, inputEl, range;
+ inputEl = $(e.currentTarget);
+ if (e.which === 13 || e.which === 27) {
+ e.preventDefault();
+ if (e.which === 13) {
+ _this._resizeImg(inputEl);
+ } else {
+ _this._restoreImg();
+ }
+ $img = _this.target;
+ _this.hide();
+ range = document.createRange();
+ return _this.button.editor.selection.setRangeAfter($img, range);
+ } else if (e.which === 9) {
+ return _this.el.data('popover').refresh();
+ }
+ };
+ })(this));
+ this.altEl.on('keydown', (function(_this) {
+ return function(e) {
+ var range;
+ if (e.which === 13) {
+ e.preventDefault();
+ range = document.createRange();
+ _this.button.editor.selection.setRangeAfter(_this.target, range);
+ return _this.hide();
+ }
+ };
+ })(this));
+ this.altEl.on('keyup', (function(_this) {
+ return function(e) {
+ if (e.which === 13 || e.which === 27 || e.which === 9) {
+ return;
+ }
+ _this.alt = _this.altEl.val();
+ return _this.target.attr('alt', _this.alt);
+ };
+ })(this));
+ this.el.find('.btn-restore').on('click', (function(_this) {
+ return function(e) {
+ _this._restoreImg();
+ return _this.el.data('popover').refresh();
+ };
+ })(this));
+ this.editor.on('valuechanged', (function(_this) {
+ return function(e) {
+ if (_this.active) {
+ return _this.refresh();
+ }
+ };
+ })(this));
+ return this._initUploader();
+ };
+
+ ImagePopover.prototype._initUploader = function() {
+ var $uploadBtn, createInput;
+ $uploadBtn = this.el.find('.btn-upload');
+ if (this.editor.uploader == null) {
+ $uploadBtn.remove();
+ return;
+ }
+ createInput = (function(_this) {
+ return function() {
+ if (_this.input) {
+ _this.input.remove();
+ }
+ return _this.input = $('', {
+ type: 'file',
+ title: _this._t('uploadImage'),
+ multiple: true,
+ accept: 'image/*'
+ }).appendTo($uploadBtn);
+ };
+ })(this);
+ createInput();
+ this.el.on('click mousedown', 'input[type=file]', function(e) {
+ return e.stopPropagation();
+ });
+ return this.el.on('change', 'input[type=file]', (function(_this) {
+ return function(e) {
+ _this.editor.uploader.upload(_this.input, {
+ inline: true,
+ img: _this.target
+ });
+ return createInput();
+ };
+ })(this));
+ };
+
+ ImagePopover.prototype._resizeImg = function(inputEl, onlySetVal) {
+ var height, value, width;
+ if (onlySetVal == null) {
+ onlySetVal = false;
+ }
+ value = inputEl.val() * 1;
+ if (!(this.target && ($.isNumeric(value) || value < 0))) {
+ return;
+ }
+ if (inputEl.is(this.widthEl)) {
+ width = value;
+ height = this.height * value / this.width;
+ this.heightEl.val(height);
+ } else {
+ height = value;
+ width = this.width * value / this.height;
+ this.widthEl.val(width);
+ }
+ if (!onlySetVal) {
+ this.target.attr({
+ width: width,
+ height: height
+ });
+ return this.editor.trigger('valuechanged');
+ }
+ };
+
+ ImagePopover.prototype._restoreImg = function() {
+ var ref, size;
+ size = ((ref = this.target.data('image-size')) != null ? ref.split(",") : void 0) || [this.width, this.height];
+ this.target.attr({
+ width: size[0] * 1,
+ height: size[1] * 1
+ });
+ this.widthEl.val(size[0]);
+ this.heightEl.val(size[1]);
+ return this.editor.trigger('valuechanged');
+ };
+
+ ImagePopover.prototype._loadImage = function(src, callback) {
+ if (/^data:image/.test(src) && !this.editor.uploader) {
+ if (callback) {
+ callback(false);
+ }
+ return;
+ }
+ if (this.target.attr('src') === src) {
+ return;
+ }
+ return this.button.loadImage(this.target, src, (function(_this) {
+ return function(img) {
+ var blob;
+ if (!img) {
+ return;
+ }
+ if (_this.active) {
+ _this.width = img.width;
+ _this.height = img.height;
+ _this.widthEl.val(_this.width);
+ _this.heightEl.val(_this.height);
+ }
+ if (/^data:image/.test(src)) {
+ blob = _this.editor.util.dataURLtoBlob(src);
+ blob.name = "Base64 Image.png";
+ _this.editor.uploader.upload(blob, {
+ inline: true,
+ img: _this.target
+ });
+ } else {
+ _this.editor.trigger('valuechanged');
+ }
+ if (callback) {
+ return callback(img);
+ }
+ };
+ })(this));
+ };
+
+ ImagePopover.prototype.show = function() {
+ var $img, args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ ImagePopover.__super__.show.apply(this, args);
+ $img = this.target;
+ this.width = $img.width();
+ this.height = $img.height();
+ this.alt = $img.attr('alt');
+ if ($img.hasClass('uploading')) {
+ return this.srcEl.val(this._t('uploading')).prop('disabled', true);
+ } else {
+ this.srcEl.val($img.attr('src')).prop('disabled', false);
+ this.widthEl.val(this.width);
+ this.heightEl.val(this.height);
+ return this.altEl.val(this.alt);
+ }
+ };
+
+ return ImagePopover;
+
+})(Popover);
+
+Simditor.Toolbar.addButton(ImageButton);
+
+IndentButton = (function(superClass) {
+ extend(IndentButton, superClass);
+
+ function IndentButton() {
+ return IndentButton.__super__.constructor.apply(this, arguments);
+ }
+
+ IndentButton.prototype.name = 'indent';
+
+ IndentButton.prototype.icon = 'indent';
+
+ IndentButton.prototype._init = function() {
+ this.title = this._t(this.name) + ' (Tab)';
+ return IndentButton.__super__._init.call(this);
+ };
+
+ IndentButton.prototype._status = function() {};
+
+ IndentButton.prototype.command = function() {
+ return this.editor.indentation.indent();
+ };
+
+ return IndentButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(IndentButton);
+
+OutdentButton = (function(superClass) {
+ extend(OutdentButton, superClass);
+
+ function OutdentButton() {
+ return OutdentButton.__super__.constructor.apply(this, arguments);
+ }
+
+ OutdentButton.prototype.name = 'outdent';
+
+ OutdentButton.prototype.icon = 'outdent';
+
+ OutdentButton.prototype._init = function() {
+ this.title = this._t(this.name) + ' (Shift + Tab)';
+ return OutdentButton.__super__._init.call(this);
+ };
+
+ OutdentButton.prototype._status = function() {};
+
+ OutdentButton.prototype.command = function() {
+ return this.editor.indentation.indent(true);
+ };
+
+ return OutdentButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(OutdentButton);
+
+HrButton = (function(superClass) {
+ extend(HrButton, superClass);
+
+ function HrButton() {
+ return HrButton.__super__.constructor.apply(this, arguments);
+ }
+
+ HrButton.prototype.name = 'hr';
+
+ HrButton.prototype.icon = 'minus';
+
+ HrButton.prototype.htmlTag = 'hr';
+
+ HrButton.prototype._status = function() {};
+
+ HrButton.prototype.command = function() {
+ var $hr, $newBlock, $nextBlock, $rootBlock;
+ $rootBlock = this.editor.selection.rootNodes().first();
+ $nextBlock = $rootBlock.next();
+ if ($nextBlock.length > 0) {
+ this.editor.selection.save();
+ } else {
+ $newBlock = $('').append(this.editor.util.phBr);
+ }
+ $hr = $('
').insertAfter($rootBlock);
+ if ($newBlock) {
+ $newBlock.insertAfter($hr);
+ this.editor.selection.setRangeAtStartOf($newBlock);
+ } else {
+ this.editor.selection.restore();
+ }
+ return this.editor.trigger('valuechanged');
+ };
+
+ return HrButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(HrButton);
+
+TableButton = (function(superClass) {
+ extend(TableButton, superClass);
+
+ function TableButton() {
+ return TableButton.__super__.constructor.apply(this, arguments);
+ }
+
+ TableButton.prototype.name = 'table';
+
+ TableButton.prototype.icon = 'table';
+
+ TableButton.prototype.htmlTag = 'table';
+
+ TableButton.prototype.disableTag = 'pre, li, blockquote';
+
+ TableButton.prototype.menu = true;
+
+ TableButton.prototype._init = function() {
+ TableButton.__super__._init.call(this);
+ $.merge(this.editor.formatter._allowedTags, ['thead', 'th', 'tbody', 'tr', 'td', 'colgroup', 'col']);
+ $.extend(this.editor.formatter._allowedAttributes, {
+ td: ['rowspan', 'colspan'],
+ col: ['width']
+ });
+ $.extend(this.editor.formatter._allowedStyles, {
+ td: ['text-align'],
+ th: ['text-align']
+ });
+ this._initShortcuts();
+ this.editor.on('decorate', (function(_this) {
+ return function(e, $el) {
+ return $el.find('table').each(function(i, table) {
+ return _this.decorate($(table));
+ });
+ };
+ })(this));
+ this.editor.on('undecorate', (function(_this) {
+ return function(e, $el) {
+ return $el.find('table').each(function(i, table) {
+ return _this.undecorate($(table));
+ });
+ };
+ })(this));
+ this.editor.on('selectionchanged.table', (function(_this) {
+ return function(e) {
+ var $container, range;
+ _this.editor.body.find('.simditor-table td, .simditor-table th').removeClass('active');
+ range = _this.editor.selection.range();
+ if (!range) {
+ return;
+ }
+ $container = _this.editor.selection.containerNode();
+ if (range.collapsed && $container.is('.simditor-table')) {
+ if (_this.editor.selection.rangeAtStartOf($container)) {
+ $container = $container.find('th:first');
+ } else {
+ $container = $container.find('td:last');
+ }
+ _this.editor.selection.setRangeAtEndOf($container);
+ }
+ return $container.closest('td, th', _this.editor.body).addClass('active');
+ };
+ })(this));
+ this.editor.on('blur.table', (function(_this) {
+ return function(e) {
+ return _this.editor.body.find('.simditor-table td, .simditor-table th').removeClass('active');
+ };
+ })(this));
+ this.editor.keystroke.add('up', 'td', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'up');
+ return true;
+ };
+ })(this));
+ this.editor.keystroke.add('up', 'th', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'up');
+ return true;
+ };
+ })(this));
+ this.editor.keystroke.add('down', 'td', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'down');
+ return true;
+ };
+ })(this));
+ return this.editor.keystroke.add('down', 'th', (function(_this) {
+ return function(e, $node) {
+ _this._tdNav($node, 'down');
+ return true;
+ };
+ })(this));
+ };
+
+ TableButton.prototype._tdNav = function($td, direction) {
+ var $anotherTr, $tr, action, anotherTag, index, parentTag, ref;
+ if (direction == null) {
+ direction = 'up';
+ }
+ action = direction === 'up' ? 'prev' : 'next';
+ ref = direction === 'up' ? ['tbody', 'thead'] : ['thead', 'tbody'], parentTag = ref[0], anotherTag = ref[1];
+ $tr = $td.parent('tr');
+ $anotherTr = this["_" + action + "Row"]($tr);
+ if (!($anotherTr.length > 0)) {
+ return true;
+ }
+ index = $tr.find('td, th').index($td);
+ return this.editor.selection.setRangeAtEndOf($anotherTr.find('td, th').eq(index));
+ };
+
+ TableButton.prototype._nextRow = function($tr) {
+ var $nextTr;
+ $nextTr = $tr.next('tr');
+ if ($nextTr.length < 1 && $tr.parent('thead').length > 0) {
+ $nextTr = $tr.parent('thead').next('tbody').find('tr:first');
+ }
+ return $nextTr;
+ };
+
+ TableButton.prototype._prevRow = function($tr) {
+ var $prevTr;
+ $prevTr = $tr.prev('tr');
+ if ($prevTr.length < 1 && $tr.parent('tbody').length > 0) {
+ $prevTr = $tr.parent('tbody').prev('thead').find('tr');
+ }
+ return $prevTr;
+ };
+
+ TableButton.prototype.initResize = function($table) {
+ var $colgroup, $resizeHandle, $wrapper;
+ $wrapper = $table.parent('.simditor-table');
+ $colgroup = $table.find('colgroup');
+ if ($colgroup.length < 1) {
+ $colgroup = $('').prependTo($table);
+ $table.find('thead tr th').each(function(i, td) {
+ var $col;
+ return $col = $('').appendTo($colgroup);
+ });
+ this.refreshTableWidth($table);
+ }
+ $resizeHandle = $('', {
+ "class": 'simditor-resize-handle',
+ contenteditable: 'false'
+ }).appendTo($wrapper);
+ $wrapper.on('mousemove', 'td, th', function(e) {
+ var $col, $td, index, ref, ref1, x;
+ if ($wrapper.hasClass('resizing')) {
+ return;
+ }
+ $td = $(e.currentTarget);
+ x = e.pageX - $(e.currentTarget).offset().left;
+ if (x < 5 && $td.prev().length > 0) {
+ $td = $td.prev();
+ }
+ if ($td.next('td, th').length < 1) {
+ $resizeHandle.hide();
+ return;
+ }
+ if ((ref = $resizeHandle.data('td')) != null ? ref.is($td) : void 0) {
+ $resizeHandle.show();
+ return;
+ }
+ index = $td.parent().find('td, th').index($td);
+ $col = $colgroup.find('col').eq(index);
+ if ((ref1 = $resizeHandle.data('col')) != null ? ref1.is($col) : void 0) {
+ $resizeHandle.show();
+ return;
+ }
+ return $resizeHandle.css('left', $td.position().left + $td.outerWidth() - 5).data('td', $td).data('col', $col).show();
+ });
+ $wrapper.on('mouseleave', function(e) {
+ return $resizeHandle.hide();
+ });
+ return $wrapper.on('mousedown', '.simditor-resize-handle', function(e) {
+ var $handle, $leftCol, $leftTd, $rightCol, $rightTd, minWidth, startHandleLeft, startLeftWidth, startRightWidth, startX, tableWidth;
+ $handle = $(e.currentTarget);
+ $leftTd = $handle.data('td');
+ $leftCol = $handle.data('col');
+ $rightTd = $leftTd.next('td, th');
+ $rightCol = $leftCol.next('col');
+ startX = e.pageX;
+ startLeftWidth = $leftTd.outerWidth() * 1;
+ startRightWidth = $rightTd.outerWidth() * 1;
+ startHandleLeft = parseFloat($handle.css('left'));
+ tableWidth = $leftTd.closest('table').width();
+ minWidth = 50;
+ $(document).on('mousemove.simditor-resize-table', function(e) {
+ var deltaX, leftWidth, rightWidth;
+ deltaX = e.pageX - startX;
+ leftWidth = startLeftWidth + deltaX;
+ rightWidth = startRightWidth - deltaX;
+ if (leftWidth < minWidth) {
+ leftWidth = minWidth;
+ deltaX = minWidth - startLeftWidth;
+ rightWidth = startRightWidth - deltaX;
+ } else if (rightWidth < minWidth) {
+ rightWidth = minWidth;
+ deltaX = startRightWidth - minWidth;
+ leftWidth = startLeftWidth + deltaX;
+ }
+ $leftCol.attr('width', (leftWidth / tableWidth * 100) + '%');
+ $rightCol.attr('width', (rightWidth / tableWidth * 100) + '%');
+ return $handle.css('left', startHandleLeft + deltaX);
+ });
+ $(document).one('mouseup.simditor-resize-table', function(e) {
+ $(document).off('.simditor-resize-table');
+ return $wrapper.removeClass('resizing');
+ });
+ $wrapper.addClass('resizing');
+ return false;
+ });
+ };
+
+ TableButton.prototype._initShortcuts = function() {
+ this.editor.hotkeys.add('ctrl+alt+up', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertRowAbove]').click();
+ return false;
+ };
+ })(this));
+ this.editor.hotkeys.add('ctrl+alt+down', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertRowBelow]').click();
+ return false;
+ };
+ })(this));
+ this.editor.hotkeys.add('ctrl+alt+left', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertColLeft]').click();
+ return false;
+ };
+ })(this));
+ return this.editor.hotkeys.add('ctrl+alt+right', (function(_this) {
+ return function(e) {
+ _this.editMenu.find('.menu-item[data-param=insertColRight]').click();
+ return false;
+ };
+ })(this));
+ };
+
+ TableButton.prototype.decorate = function($table) {
+ var $headRow, $tbody, $thead;
+ if ($table.parent('.simditor-table').length > 0) {
+ this.undecorate($table);
+ }
+ $table.wrap('');
+ if ($table.find('thead').length < 1) {
+ $thead = $('');
+ $headRow = $table.find('tr').first();
+ $thead.append($headRow);
+ this._changeCellTag($headRow, 'th');
+ $tbody = $table.find('tbody');
+ if ($tbody.length > 0) {
+ $tbody.before($thead);
+ } else {
+ $table.prepend($thead);
+ }
+ }
+ this.initResize($table);
+ return $table.parent();
+ };
+
+ TableButton.prototype.undecorate = function($table) {
+ if (!($table.parent('.simditor-table').length > 0)) {
+ return;
+ }
+ return $table.parent().replaceWith($table);
+ };
+
+ TableButton.prototype.renderMenu = function() {
+ var $table;
+ $("\n").appendTo(this.menuWrapper);
+ this.createMenu = this.menuWrapper.find('.menu-create-table');
+ this.editMenu = this.menuWrapper.find('.menu-edit-table');
+ $table = this.createTable(6, 6).appendTo(this.createMenu);
+ this.createMenu.on('mouseenter', 'td, th', (function(_this) {
+ return function(e) {
+ var $td, $tr, $trs, num;
+ _this.createMenu.find('td, th').removeClass('selected');
+ $td = $(e.currentTarget);
+ $tr = $td.parent();
+ num = $tr.find('td, th').index($td) + 1;
+ $trs = $tr.prevAll('tr').addBack();
+ if ($tr.parent().is('tbody')) {
+ $trs = $trs.add($table.find('thead tr'));
+ }
+ return $trs.find("td:lt(" + num + "), th:lt(" + num + ")").addClass('selected');
+ };
+ })(this));
+ this.createMenu.on('mouseleave', function(e) {
+ return $(e.currentTarget).find('td, th').removeClass('selected');
+ });
+ return this.createMenu.on('mousedown', 'td, th', (function(_this) {
+ return function(e) {
+ var $closestBlock, $td, $tr, colNum, rowNum;
+ _this.wrapper.removeClass('menu-on');
+ if (!_this.editor.inputManager.focused) {
+ return;
+ }
+ $td = $(e.currentTarget);
+ $tr = $td.parent();
+ colNum = $tr.find('td').index($td) + 1;
+ rowNum = $tr.prevAll('tr').length + 1;
+ if ($tr.parent().is('tbody')) {
+ rowNum += 1;
+ }
+ $table = _this.createTable(rowNum, colNum, true);
+ $closestBlock = _this.editor.selection.blockNodes().last();
+ if (_this.editor.util.isEmptyNode($closestBlock)) {
+ $closestBlock.replaceWith($table);
+ } else {
+ $closestBlock.after($table);
+ }
+ _this.decorate($table);
+ _this.editor.selection.setRangeAtStartOf($table.find('th:first'));
+ _this.editor.trigger('valuechanged');
+ return false;
+ };
+ })(this));
+ };
+
+ TableButton.prototype.createTable = function(row, col, phBr) {
+ var $table, $tbody, $td, $thead, $tr, c, k, l, r, ref, ref1;
+ $table = $('');
+ $thead = $('').appendTo($table);
+ $tbody = $('').appendTo($table);
+ for (r = k = 0, ref = row; 0 <= ref ? k < ref : k > ref; r = 0 <= ref ? ++k : --k) {
+ $tr = $('
');
+ $tr.appendTo(r === 0 ? $thead : $tbody);
+ for (c = l = 0, ref1 = col; 0 <= ref1 ? l < ref1 : l > ref1; c = 0 <= ref1 ? ++l : --l) {
+ $td = $(r === 0 ? ' | ' : ' | ').appendTo($tr);
+ if (phBr) {
+ $td.append(this.editor.util.phBr);
+ }
+ }
+ }
+ return $table;
+ };
+
+ TableButton.prototype.refreshTableWidth = function($table) {
+ var cols, tableWidth;
+ tableWidth = $table.width();
+ cols = $table.find('col');
+ return $table.find('thead tr th').each(function(i, td) {
+ var $col;
+ $col = cols.eq(i);
+ return $col.attr('width', ($(td).outerWidth() / tableWidth * 100) + '%');
+ });
+ };
+
+ TableButton.prototype.setActive = function(active) {
+ TableButton.__super__.setActive.call(this, active);
+ if (active) {
+ this.createMenu.hide();
+ return this.editMenu.show();
+ } else {
+ this.createMenu.show();
+ return this.editMenu.hide();
+ }
+ };
+
+ TableButton.prototype._changeCellTag = function($tr, tagName) {
+ return $tr.find('td, th').each(function(i, cell) {
+ var $cell;
+ $cell = $(cell);
+ return $cell.replaceWith("<" + tagName + ">" + ($cell.html()) + "" + tagName + ">");
+ });
+ };
+
+ TableButton.prototype.deleteRow = function($td) {
+ var $newTr, $tr, index;
+ $tr = $td.parent('tr');
+ if ($tr.closest('table').find('tr').length < 1) {
+ return this.deleteTable($td);
+ } else {
+ $newTr = this._nextRow($tr);
+ if (!($newTr.length > 0)) {
+ $newTr = this._prevRow($tr);
+ }
+ index = $tr.find('td, th').index($td);
+ if ($tr.parent().is('thead')) {
+ $newTr.appendTo($tr.parent());
+ this._changeCellTag($newTr, 'th');
+ }
+ $tr.remove();
+ return this.editor.selection.setRangeAtEndOf($newTr.find('td, th').eq(index));
+ }
+ };
+
+ TableButton.prototype.insertRow = function($td, direction) {
+ var $newTr, $table, $tr, cellTag, colNum, i, index, k, ref;
+ if (direction == null) {
+ direction = 'after';
+ }
+ $tr = $td.parent('tr');
+ $table = $tr.closest('table');
+ colNum = 0;
+ $table.find('tr').each(function(i, tr) {
+ return colNum = Math.max(colNum, $(tr).find('td').length);
+ });
+ index = $tr.find('td, th').index($td);
+ $newTr = $('
');
+ cellTag = 'td';
+ if (direction === 'after' && $tr.parent().is('thead')) {
+ $tr.parent().next('tbody').prepend($newTr);
+ } else if (direction === 'before' && $tr.parent().is('thead')) {
+ $tr.before($newTr);
+ $tr.parent().next('tbody').prepend($tr);
+ this._changeCellTag($tr, 'td');
+ cellTag = 'th';
+ } else {
+ $tr[direction]($newTr);
+ }
+ for (i = k = 1, ref = colNum; 1 <= ref ? k <= ref : k >= ref; i = 1 <= ref ? ++k : --k) {
+ $("<" + cellTag + "/>").append(this.editor.util.phBr).appendTo($newTr);
+ }
+ return this.editor.selection.setRangeAtStartOf($newTr.find('td, th').eq(index));
+ };
+
+ TableButton.prototype.deleteCol = function($td) {
+ var $newTd, $table, $tr, index, noOtherCol, noOtherRow;
+ $tr = $td.parent('tr');
+ noOtherRow = $tr.closest('table').find('tr').length < 2;
+ noOtherCol = $td.siblings('td, th').length < 1;
+ if (noOtherRow && noOtherCol) {
+ return this.deleteTable($td);
+ } else {
+ index = $tr.find('td, th').index($td);
+ $newTd = $td.next('td, th');
+ if (!($newTd.length > 0)) {
+ $newTd = $tr.prev('td, th');
+ }
+ $table = $tr.closest('table');
+ $table.find('col').eq(index).remove();
+ $table.find('tr').each(function(i, tr) {
+ return $(tr).find('td, th').eq(index).remove();
+ });
+ this.refreshTableWidth($table);
+ return this.editor.selection.setRangeAtEndOf($newTd);
+ }
+ };
+
+ TableButton.prototype.insertCol = function($td, direction) {
+ var $col, $newCol, $newTd, $table, $tr, index, tableWidth, width;
+ if (direction == null) {
+ direction = 'after';
+ }
+ $tr = $td.parent('tr');
+ index = $tr.find('td, th').index($td);
+ $table = $td.closest('table');
+ $col = $table.find('col').eq(index);
+ $table.find('tr').each((function(_this) {
+ return function(i, tr) {
+ var $newTd, cellTag;
+ cellTag = $(tr).parent().is('thead') ? 'th' : 'td';
+ $newTd = $("<" + cellTag + "/>").append(_this.editor.util.phBr);
+ return $(tr).find('td, th').eq(index)[direction]($newTd);
+ };
+ })(this));
+ $newCol = $('');
+ $col[direction]($newCol);
+ tableWidth = $table.width();
+ width = Math.max(parseFloat($col.attr('width')) / 2, 50 / tableWidth * 100);
+ $col.attr('width', width + '%');
+ $newCol.attr('width', width + '%');
+ this.refreshTableWidth($table);
+ $newTd = direction === 'after' ? $td.next('td, th') : $td.prev('td, th');
+ return this.editor.selection.setRangeAtStartOf($newTd);
+ };
+
+ TableButton.prototype.deleteTable = function($td) {
+ var $block, $table;
+ $table = $td.closest('.simditor-table');
+ $block = $table.next('p');
+ $table.remove();
+ if ($block.length > 0) {
+ return this.editor.selection.setRangeAtStartOf($block);
+ }
+ };
+
+ TableButton.prototype.command = function(param) {
+ var $td;
+ $td = this.editor.selection.containerNode().closest('td, th');
+ if (!($td.length > 0)) {
+ return;
+ }
+ if (param === 'deleteRow') {
+ this.deleteRow($td);
+ } else if (param === 'insertRowAbove') {
+ this.insertRow($td, 'before');
+ } else if (param === 'insertRowBelow') {
+ this.insertRow($td);
+ } else if (param === 'deleteCol') {
+ this.deleteCol($td);
+ } else if (param === 'insertColLeft') {
+ this.insertCol($td, 'before');
+ } else if (param === 'insertColRight') {
+ this.insertCol($td);
+ } else if (param === 'deleteTable') {
+ this.deleteTable($td);
+ } else {
+ return;
+ }
+ return this.editor.trigger('valuechanged');
+ };
+
+ return TableButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(TableButton);
+
+StrikethroughButton = (function(superClass) {
+ extend(StrikethroughButton, superClass);
+
+ function StrikethroughButton() {
+ return StrikethroughButton.__super__.constructor.apply(this, arguments);
+ }
+
+ StrikethroughButton.prototype.name = 'strikethrough';
+
+ StrikethroughButton.prototype.icon = 'strikethrough';
+
+ StrikethroughButton.prototype.htmlTag = 'strike';
+
+ StrikethroughButton.prototype.disableTag = 'pre';
+
+ StrikethroughButton.prototype._activeStatus = function() {
+ var active;
+ active = document.queryCommandState('strikethrough') === true;
+ this.setActive(active);
+ return this.active;
+ };
+
+ StrikethroughButton.prototype.command = function() {
+ document.execCommand('strikethrough');
+ if (!this.editor.util.support.oninput) {
+ this.editor.trigger('valuechanged');
+ }
+ return $(document).trigger('selectionchange');
+ };
+
+ return StrikethroughButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(StrikethroughButton);
+
+AlignmentButton = (function(superClass) {
+ extend(AlignmentButton, superClass);
+
+ function AlignmentButton() {
+ return AlignmentButton.__super__.constructor.apply(this, arguments);
+ }
+
+ AlignmentButton.prototype.name = "alignment";
+
+ AlignmentButton.prototype.icon = 'align-left';
+
+ AlignmentButton.prototype.htmlTag = 'p, h1, h2, h3, h4, td, th';
+
+ AlignmentButton.prototype._init = function() {
+ this.menu = [
+ {
+ name: 'left',
+ text: this._t('alignLeft'),
+ icon: 'align-left',
+ param: 'left'
+ }, {
+ name: 'center',
+ text: this._t('alignCenter'),
+ icon: 'align-center',
+ param: 'center'
+ }, {
+ name: 'right',
+ text: this._t('alignRight'),
+ icon: 'align-right',
+ param: 'right'
+ }
+ ];
+ return AlignmentButton.__super__._init.call(this);
+ };
+
+ AlignmentButton.prototype.setActive = function(active, align) {
+ if (align == null) {
+ align = 'left';
+ }
+ if (align !== 'left' && align !== 'center' && align !== 'right') {
+ align = 'left';
+ }
+ if (align === 'left') {
+ AlignmentButton.__super__.setActive.call(this, false);
+ } else {
+ AlignmentButton.__super__.setActive.call(this, active);
+ }
+ this.el.removeClass('align-left align-center align-right');
+ if (active) {
+ this.el.addClass('align-' + align);
+ }
+ this.setIcon('align-' + align);
+ return this.menuEl.find('.menu-item').show().end().find('.menu-item-' + align).hide();
+ };
+
+ AlignmentButton.prototype._status = function() {
+ this.nodes = this.editor.selection.nodes().filter(this.htmlTag);
+ if (this.nodes.length < 1) {
+ this.setDisabled(true);
+ return this.setActive(false);
+ } else {
+ this.setDisabled(false);
+ return this.setActive(true, this.nodes.first().css('text-align'));
+ }
+ };
+
+ AlignmentButton.prototype.command = function(align) {
+ if (align !== 'left' && align !== 'center' && align !== 'right') {
+ throw new Error("simditor alignment button: invalid align " + align);
+ }
+ this.nodes.css({
+ 'text-align': align === 'left' ? '' : align
+ });
+ this.editor.trigger('valuechanged');
+ return this.editor.inputManager.throttledSelectionChanged();
+ };
+
+ return AlignmentButton;
+
+})(Button);
+
+Simditor.Toolbar.addButton(AlignmentButton);
+
+return Simditor;
+
+}));
diff --git a/resources/editor/js/uploader.js b/resources/editor/js/uploader.js
new file mode 100644
index 000000000..d96860ec0
--- /dev/null
+++ b/resources/editor/js/uploader.js
@@ -0,0 +1,261 @@
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module unless amdModuleId is set
+ define('simple-uploader', ["jquery","simple-module"], function ($, SimpleModule) {
+ return (root['uploader'] = 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['uploader'] = factory(jQuery,SimpleModule);
+ }
+}(this, function ($, SimpleModule) {
+
+var Uploader, uploader,
+ 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;
+
+Uploader = (function(superClass) {
+ extend(Uploader, superClass);
+
+ function Uploader() {
+ return Uploader.__super__.constructor.apply(this, arguments);
+ }
+
+ Uploader.count = 0;
+
+ Uploader.prototype.opts = {
+ url: '',
+ params: null,
+ fileKey: 'upload_file',
+ connectionCount: 3
+ };
+
+ Uploader.prototype._init = function() {
+ this.files = [];
+ this.queue = [];
+ this.id = ++Uploader.count;
+ this.on('uploadcomplete', (function(_this) {
+ return function(e, file) {
+ _this.files.splice($.inArray(file, _this.files), 1);
+ if (_this.queue.length > 0 && _this.files.length < _this.opts.connectionCount) {
+ return _this.upload(_this.queue.shift());
+ } else {
+ return _this.uploading = false;
+ }
+ };
+ })(this));
+ return $(window).on('beforeunload.uploader-' + this.id, (function(_this) {
+ return function(e) {
+ if (!_this.uploading) {
+ return;
+ }
+ e.originalEvent.returnValue = _this._t('leaveConfirm');
+ return _this._t('leaveConfirm');
+ };
+ })(this));
+ };
+
+ Uploader.prototype.generateId = (function() {
+ var id;
+ id = 0;
+ return function() {
+ return id += 1;
+ };
+ })();
+
+ Uploader.prototype.upload = function(file, opts) {
+ var f, i, key, len;
+ if (opts == null) {
+ opts = {};
+ }
+ if (file == null) {
+ return;
+ }
+ if ($.isArray(file) || file instanceof FileList) {
+ for (i = 0, len = file.length; i < len; i++) {
+ f = file[i];
+ this.upload(f, opts);
+ }
+ } else if ($(file).is('input:file')) {
+ key = $(file).attr('name');
+ if (key) {
+ opts.fileKey = key;
+ }
+ this.upload($.makeArray($(file)[0].files), opts);
+ } else if (!file.id || !file.obj) {
+ file = this.getFile(file);
+ }
+ if (!(file && file.obj)) {
+ return;
+ }
+ $.extend(file, opts);
+ if (this.files.length >= this.opts.connectionCount) {
+ this.queue.push(file);
+ return;
+ }
+ if (this.triggerHandler('beforeupload', [file]) === false) {
+ return;
+ }
+ this.files.push(file);
+ this._xhrUpload(file);
+ return this.uploading = true;
+ };
+
+ Uploader.prototype.getFile = function(fileObj) {
+ var name, ref, ref1;
+ if (fileObj instanceof window.File || fileObj instanceof window.Blob) {
+ name = (ref = fileObj.fileName) != null ? ref : fileObj.name;
+ } else {
+ return null;
+ }
+ return {
+ id: this.generateId(),
+ url: this.opts.url,
+ params: this.opts.params,
+ fileKey: this.opts.fileKey,
+ name: name,
+ size: (ref1 = fileObj.fileSize) != null ? ref1 : fileObj.size,
+ ext: name ? name.split('.').pop().toLowerCase() : '',
+ obj: fileObj
+ };
+ };
+
+ Uploader.prototype._xhrUpload = function(file) {
+ var formData, k, ref, v;
+ formData = new FormData();
+ formData.append(file.fileKey, file.obj);
+ formData.append("original_filename", file.name);
+ if (file.params) {
+ ref = file.params;
+ for (k in ref) {
+ v = ref[k];
+ formData.append(k, v);
+ }
+ }
+ return file.xhr = $.ajax({
+ url: file.url,
+ data: formData,
+ processData: false,
+ contentType: false,
+ type: 'POST',
+ headers: {
+ 'X-File-Name': encodeURIComponent(file.name)
+ },
+ xhr: function() {
+ var req;
+ req = $.ajaxSettings.xhr();
+ if (req) {
+ req.upload.onprogress = (function(_this) {
+ return function(e) {
+ return _this.progress(e);
+ };
+ })(this);
+ }
+ return req;
+ },
+ progress: (function(_this) {
+ return function(e) {
+ if (!e.lengthComputable) {
+ return;
+ }
+ return _this.trigger('uploadprogress', [file, e.loaded, e.total]);
+ };
+ })(this),
+ error: (function(_this) {
+ return function(xhr, status, err) {
+ return _this.trigger('uploaderror', [file, xhr, status]);
+ };
+ })(this),
+ success: (function(_this) {
+ return function(result) {
+ _this.trigger('uploadprogress', [file, file.size, file.size]);
+ _this.trigger('uploadsuccess', [file, result]);
+ return $(document).trigger('uploadsuccess', [file, result, _this]);
+ };
+ })(this),
+ complete: (function(_this) {
+ return function(xhr, status) {
+ return _this.trigger('uploadcomplete', [file, xhr.responseText]);
+ };
+ })(this)
+ });
+ };
+
+ Uploader.prototype.cancel = function(file) {
+ var f, i, len, ref;
+ if (!file.id) {
+ ref = this.files;
+ for (i = 0, len = ref.length; i < len; i++) {
+ f = ref[i];
+ if (f.id === file * 1) {
+ file = f;
+ break;
+ }
+ }
+ }
+ this.trigger('uploadcancel', [file]);
+ if (file.xhr) {
+ file.xhr.abort();
+ }
+ return file.xhr = null;
+ };
+
+ Uploader.prototype.readImageFile = function(fileObj, callback) {
+ var fileReader, img;
+ if (!$.isFunction(callback)) {
+ return;
+ }
+ img = new Image();
+ img.onload = function() {
+ return callback(img);
+ };
+ img.onerror = function() {
+ return callback();
+ };
+ if (window.FileReader && FileReader.prototype.readAsDataURL && /^image/.test(fileObj.type)) {
+ fileReader = new FileReader();
+ fileReader.onload = function(e) {
+ return img.src = e.target.result;
+ };
+ return fileReader.readAsDataURL(fileObj);
+ } else {
+ return callback();
+ }
+ };
+
+ Uploader.prototype.destroy = function() {
+ var file, i, len, ref;
+ this.queue.length = 0;
+ ref = this.files;
+ for (i = 0, len = ref.length; i < len; i++) {
+ file = ref[i];
+ this.cancel(file);
+ }
+ $(window).off('.uploader-' + this.id);
+ return $(document).off('.uploader-' + this.id);
+ };
+
+ Uploader.i18n = {
+ 'zh-CN': {
+ leaveConfirm: '正在上传文件,如果离开上传会自动取消'
+ }
+ };
+
+ Uploader.locale = 'zh-CN';
+
+ return Uploader;
+
+})(SimpleModule);
+
+uploader = function(opts) {
+ return new Uploader(opts);
+};
+
+return uploader;
+
+}));
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index 03de510a0..be1de93c2 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -14,6 +14,8 @@
+ @yield('styles')
+
@@ -34,6 +36,9 @@
+
+ @yield('scripts')
+