summernote-rails 0.6.2.1 → 0.6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +30 -0
- data/lib/summernote-rails/version.rb +1 -1
- data/vendor/assets/javascripts/summernote/locales/ar-AR.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/ca-ES.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/cs-CZ.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/da-DK.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/de-DE.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/es-ES.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/es-EU.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/fa-IR.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/fi-FI.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/fr-FR.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/he-IL.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/hu-HU.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/id-ID.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/it-IT.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/ja-JP.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/ko-KR.js +6 -1
- data/vendor/assets/javascripts/summernote/locales/nb-NO.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/nl-NL.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/pl-PL.js +17 -7
- data/vendor/assets/javascripts/summernote/locales/pt-BR.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/ro-RO.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/ru-RU.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/sk-SK.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/sl-SI.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/sr-RS-Latin.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/sr-RS.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/sv-SE.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/th-TH.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/tr-TR.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/uk-UA.js +5 -1
- data/vendor/assets/javascripts/summernote/locales/vi-VN.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/zh-CN.js +3 -1
- data/vendor/assets/javascripts/summernote/locales/zh-TW.js +3 -1
- data/vendor/assets/javascripts/summernote/plugin/summernote-ext-hello.js +89 -0
- data/vendor/assets/javascripts/summernote/plugin/summernote-ext-video.js +573 -0
- data/vendor/assets/javascripts/summernote/summernote.js +1648 -1099
- metadata +4 -2
@@ -1,12 +1,12 @@
|
|
1
1
|
/**
|
2
|
-
* Super simple wysiwyg editor on Bootstrap v0.6.
|
2
|
+
* Super simple wysiwyg editor on Bootstrap v0.6.5
|
3
3
|
* http://summernote.org/
|
4
4
|
*
|
5
5
|
* summernote.js
|
6
6
|
* Copyright 2013-2015 Alan Hong. and other contributors
|
7
7
|
* summernote may be freely distributed under the MIT license./
|
8
8
|
*
|
9
|
-
* Date: 2015-
|
9
|
+
* Date: 2015-04-26T03:15Z
|
10
10
|
*/
|
11
11
|
(function (factory) {
|
12
12
|
/* global define */
|
@@ -227,6 +227,18 @@
|
|
227
227
|
return inverted;
|
228
228
|
};
|
229
229
|
|
230
|
+
/**
|
231
|
+
* @param {String} namespace
|
232
|
+
* @param {String} [prefix]
|
233
|
+
* @return {String}
|
234
|
+
*/
|
235
|
+
var namespaceToCamel = function (namespace, prefix) {
|
236
|
+
prefix = prefix || '';
|
237
|
+
return prefix + namespace.split('.').map(function (name) {
|
238
|
+
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
239
|
+
}).join('');
|
240
|
+
};
|
241
|
+
|
230
242
|
return {
|
231
243
|
eq: eq,
|
232
244
|
eq2: eq2,
|
@@ -238,7 +250,8 @@
|
|
238
250
|
and: and,
|
239
251
|
uniqueId: uniqueId,
|
240
252
|
rect2bnd: rect2bnd,
|
241
|
-
invertObject: invertObject
|
253
|
+
invertObject: invertObject,
|
254
|
+
namespaceToCamel: namespaceToCamel
|
242
255
|
};
|
243
256
|
})();
|
244
257
|
|
@@ -489,6 +502,7 @@
|
|
489
502
|
|
490
503
|
return {
|
491
504
|
editor: function () { return $editor; },
|
505
|
+
holder : function () { return $editor.data('holder'); },
|
492
506
|
editable: function () { return $editor; },
|
493
507
|
popover: makeFinder('#note-popover-'),
|
494
508
|
handle: makeFinder('#note-handle-'),
|
@@ -502,6 +516,7 @@
|
|
502
516
|
};
|
503
517
|
return {
|
504
518
|
editor: function () { return $editor; },
|
519
|
+
holder : function () { return $editor.data('holder'); },
|
505
520
|
dropzone: makeFinder('.note-dropzone'),
|
506
521
|
toolbar: makeFinder('.note-toolbar'),
|
507
522
|
editable: makeFinder('.note-editable'),
|
@@ -514,6 +529,30 @@
|
|
514
529
|
}
|
515
530
|
};
|
516
531
|
|
532
|
+
/**
|
533
|
+
* returns makeLayoutInfo from editor's descendant node.
|
534
|
+
*
|
535
|
+
* @private
|
536
|
+
* @param {Node} descendant
|
537
|
+
* @return {Object}
|
538
|
+
*/
|
539
|
+
var makeLayoutInfo = function (descendant) {
|
540
|
+
var $target = $(descendant).closest('.note-editor, .note-air-editor, .note-air-layout');
|
541
|
+
|
542
|
+
if (!$target.length) {
|
543
|
+
return null;
|
544
|
+
}
|
545
|
+
|
546
|
+
var $editor;
|
547
|
+
if ($target.is('.note-editor, .note-air-editor')) {
|
548
|
+
$editor = $target;
|
549
|
+
} else {
|
550
|
+
$editor = $('#note-editor-' + list.last($target.attr('id').split('-')));
|
551
|
+
}
|
552
|
+
|
553
|
+
return buildLayoutInfo($editor);
|
554
|
+
};
|
555
|
+
|
517
556
|
/**
|
518
557
|
* @method makePredByNodeName
|
519
558
|
*
|
@@ -635,6 +674,7 @@
|
|
635
674
|
|
636
675
|
/**
|
637
676
|
* blank HTML for cursor position
|
677
|
+
* - [workaround] for MSIE IE doesn't works with bogus br
|
638
678
|
*/
|
639
679
|
var blankHTML = agent.isMSIE ? ' ' : '<br>';
|
640
680
|
|
@@ -1077,6 +1117,21 @@
|
|
1077
1117
|
return null;
|
1078
1118
|
};
|
1079
1119
|
|
1120
|
+
/**
|
1121
|
+
* returns whether point has character or not.
|
1122
|
+
*
|
1123
|
+
* @param {Point} point
|
1124
|
+
* @return {Boolean}
|
1125
|
+
*/
|
1126
|
+
var isCharPoint = function (point) {
|
1127
|
+
if (!isText(point.node)) {
|
1128
|
+
return false;
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
var ch = point.node.nodeValue.charAt(point.offset - 1);
|
1132
|
+
return ch && (ch !== ' ' && ch !== NBSP_CHAR);
|
1133
|
+
};
|
1134
|
+
|
1080
1135
|
/**
|
1081
1136
|
* @method walkPoint
|
1082
1137
|
*
|
@@ -1141,33 +1196,39 @@
|
|
1141
1196
|
* split element or #text
|
1142
1197
|
*
|
1143
1198
|
* @param {BoundaryPoint} point
|
1144
|
-
* @param {
|
1199
|
+
* @param {Object} [options]
|
1200
|
+
* @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
|
1201
|
+
* @param {Boolean} [options.isNotSplitEdgePoint] - default: false
|
1145
1202
|
* @return {Node} right node of boundaryPoint
|
1146
1203
|
*/
|
1147
|
-
var splitNode = function (point,
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1204
|
+
var splitNode = function (point, options) {
|
1205
|
+
var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;
|
1206
|
+
var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;
|
1207
|
+
|
1208
|
+
// edge case
|
1209
|
+
if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {
|
1151
1210
|
if (isLeftEdgePoint(point)) {
|
1152
1211
|
return point.node;
|
1153
1212
|
} else if (isRightEdgePoint(point)) {
|
1154
1213
|
return point.node.nextSibling;
|
1155
1214
|
}
|
1215
|
+
}
|
1156
1216
|
|
1217
|
+
// split #text
|
1218
|
+
if (isText(point.node)) {
|
1157
1219
|
return point.node.splitText(point.offset);
|
1158
|
-
}
|
1220
|
+
} else {
|
1221
|
+
var childNode = point.node.childNodes[point.offset];
|
1222
|
+
var clone = insertAfter(point.node.cloneNode(false), point.node);
|
1223
|
+
appendChildNodes(clone, listNext(childNode));
|
1159
1224
|
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1225
|
+
if (!isSkipPaddingBlankHTML) {
|
1226
|
+
paddingBlankHTML(point.node);
|
1227
|
+
paddingBlankHTML(clone);
|
1228
|
+
}
|
1164
1229
|
|
1165
|
-
|
1166
|
-
paddingBlankHTML(point.node);
|
1167
|
-
paddingBlankHTML(clone);
|
1230
|
+
return clone;
|
1168
1231
|
}
|
1169
|
-
|
1170
|
-
return clone;
|
1171
1232
|
};
|
1172
1233
|
|
1173
1234
|
/**
|
@@ -1177,33 +1238,30 @@
|
|
1177
1238
|
*
|
1178
1239
|
* @param {Node} root - split root
|
1179
1240
|
* @param {BoundaryPoint} point
|
1180
|
-
* @param {
|
1241
|
+
* @param {Object} [options]
|
1242
|
+
* @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
|
1243
|
+
* @param {Boolean} [options.isNotSplitEdgePoint] - default: false
|
1181
1244
|
* @return {Node} right node of boundaryPoint
|
1182
1245
|
*/
|
1183
|
-
var splitTree = function (root, point,
|
1246
|
+
var splitTree = function (root, point, options) {
|
1184
1247
|
// ex) [#text, <span>, <p>]
|
1185
1248
|
var ancestors = listAncestor(point.node, func.eq(root));
|
1186
1249
|
|
1187
1250
|
if (!ancestors.length) {
|
1188
1251
|
return null;
|
1189
1252
|
} else if (ancestors.length === 1) {
|
1190
|
-
return splitNode(point,
|
1253
|
+
return splitNode(point, options);
|
1191
1254
|
}
|
1192
1255
|
|
1193
1256
|
return ancestors.reduce(function (node, parent) {
|
1194
|
-
var clone = insertAfter(parent.cloneNode(false), parent);
|
1195
|
-
|
1196
1257
|
if (node === point.node) {
|
1197
|
-
node = splitNode(point,
|
1258
|
+
node = splitNode(point, options);
|
1198
1259
|
}
|
1199
1260
|
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
paddingBlankHTML(clone);
|
1205
|
-
}
|
1206
|
-
return clone;
|
1261
|
+
return splitNode({
|
1262
|
+
node: parent,
|
1263
|
+
offset: node ? dom.position(node) : nodeLength(parent)
|
1264
|
+
}, options);
|
1207
1265
|
});
|
1208
1266
|
};
|
1209
1267
|
|
@@ -1231,8 +1289,16 @@
|
|
1231
1289
|
container = splitRoot.parentNode;
|
1232
1290
|
}
|
1233
1291
|
|
1234
|
-
// split with splitTree
|
1235
|
-
var pivot = splitRoot && splitTree(splitRoot, point,
|
1292
|
+
// if splitRoot is exists, split with splitTree
|
1293
|
+
var pivot = splitRoot && splitTree(splitRoot, point, {
|
1294
|
+
isSkipPaddingBlankHTML: isInline,
|
1295
|
+
isNotSplitEdgePoint: isInline
|
1296
|
+
});
|
1297
|
+
|
1298
|
+
// if container is point.node, find pivot with point.offset
|
1299
|
+
if (!pivot && container === point.node) {
|
1300
|
+
pivot = point.node.childNodes[point.offset];
|
1301
|
+
}
|
1236
1302
|
|
1237
1303
|
return {
|
1238
1304
|
rightNode: pivot,
|
@@ -1323,6 +1389,18 @@
|
|
1323
1389
|
|
1324
1390
|
var isTextarea = makePredByNodeName('TEXTAREA');
|
1325
1391
|
|
1392
|
+
/**
|
1393
|
+
* @param {jQuery} $node
|
1394
|
+
* @param {Boolean} [stripLinebreaks] - default: false
|
1395
|
+
*/
|
1396
|
+
var value = function ($node, stripLinebreaks) {
|
1397
|
+
var val = isTextarea($node[0]) ? $node.val() : $node.html();
|
1398
|
+
if (stripLinebreaks) {
|
1399
|
+
return val.replace(/[\n\r]/g, '');
|
1400
|
+
}
|
1401
|
+
return val;
|
1402
|
+
};
|
1403
|
+
|
1326
1404
|
/**
|
1327
1405
|
* @method html
|
1328
1406
|
*
|
@@ -1332,7 +1410,7 @@
|
|
1332
1410
|
* @param {Boolean} [isNewlineOnBlock]
|
1333
1411
|
*/
|
1334
1412
|
var html = function ($node, isNewlineOnBlock) {
|
1335
|
-
var markup =
|
1413
|
+
var markup = value($node);
|
1336
1414
|
|
1337
1415
|
if (isNewlineOnBlock) {
|
1338
1416
|
var regexTag = /<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g;
|
@@ -1350,14 +1428,6 @@
|
|
1350
1428
|
return markup;
|
1351
1429
|
};
|
1352
1430
|
|
1353
|
-
var value = function ($textarea, stripLinebreaks) {
|
1354
|
-
var val = $textarea.val();
|
1355
|
-
if (stripLinebreaks) {
|
1356
|
-
return val.replace(/[\n\r]/g, '');
|
1357
|
-
}
|
1358
|
-
return val;
|
1359
|
-
};
|
1360
|
-
|
1361
1431
|
return {
|
1362
1432
|
/** @property {String} NBSP_CHAR */
|
1363
1433
|
NBSP_CHAR: NBSP_CHAR,
|
@@ -1371,11 +1441,13 @@
|
|
1371
1441
|
isEditable: isEditable,
|
1372
1442
|
isControlSizing: isControlSizing,
|
1373
1443
|
buildLayoutInfo: buildLayoutInfo,
|
1444
|
+
makeLayoutInfo: makeLayoutInfo,
|
1374
1445
|
isText: isText,
|
1375
1446
|
isVoid: isVoid,
|
1376
1447
|
isPara: isPara,
|
1377
1448
|
isPurePara: isPurePara,
|
1378
1449
|
isInline: isInline,
|
1450
|
+
isBlock: func.not(isInline),
|
1379
1451
|
isBodyInline: isBodyInline,
|
1380
1452
|
isBody: isBody,
|
1381
1453
|
isParaInline: isParaInline,
|
@@ -1411,6 +1483,7 @@
|
|
1411
1483
|
isVisiblePoint: isVisiblePoint,
|
1412
1484
|
prevPointUntil: prevPointUntil,
|
1413
1485
|
nextPointUntil: nextPointUntil,
|
1486
|
+
isCharPoint: isCharPoint,
|
1414
1487
|
walkPoint: walkPoint,
|
1415
1488
|
ancestor: ancestor,
|
1416
1489
|
singleChildAncestor: singleChildAncestor,
|
@@ -1618,6 +1691,32 @@
|
|
1618
1691
|
} else {
|
1619
1692
|
nativeRng.select();
|
1620
1693
|
}
|
1694
|
+
|
1695
|
+
return this;
|
1696
|
+
};
|
1697
|
+
|
1698
|
+
/**
|
1699
|
+
* Moves the scrollbar to start container(sc) of current range
|
1700
|
+
*
|
1701
|
+
* @return {WrappedRange}
|
1702
|
+
*/
|
1703
|
+
this.scrollIntoView = function () {
|
1704
|
+
if (this.sc.scrollIntoView) {
|
1705
|
+
this.sc.scrollIntoView(false);
|
1706
|
+
}
|
1707
|
+
|
1708
|
+
return this;
|
1709
|
+
};
|
1710
|
+
|
1711
|
+
/**
|
1712
|
+
* set a focus into start container of current range
|
1713
|
+
*
|
1714
|
+
* @return {WrappedRange}
|
1715
|
+
*/
|
1716
|
+
this.focus = function () {
|
1717
|
+
this.sc.focus();
|
1718
|
+
|
1719
|
+
return this;
|
1621
1720
|
};
|
1622
1721
|
|
1623
1722
|
/**
|
@@ -1922,6 +2021,21 @@
|
|
1922
2021
|
|
1923
2022
|
return node;
|
1924
2023
|
};
|
2024
|
+
|
2025
|
+
/**
|
2026
|
+
* insert html at current cursor
|
2027
|
+
*/
|
2028
|
+
this.pasteHTML = function (markup) {
|
2029
|
+
var self = this;
|
2030
|
+
var contentsContainer = $('<div></div>').html(markup)[0];
|
2031
|
+
var childNodes = list.from(contentsContainer.childNodes);
|
2032
|
+
|
2033
|
+
this.wrapBodyInlineWithPara().deleteContents();
|
2034
|
+
|
2035
|
+
return $.map(childNodes.reverse(), function (childNode) {
|
2036
|
+
return self.insertNode(childNode);
|
2037
|
+
}).reverse();
|
2038
|
+
};
|
1925
2039
|
|
1926
2040
|
/**
|
1927
2041
|
* returns text in range
|
@@ -1932,6 +2046,37 @@
|
|
1932
2046
|
var nativeRng = nativeRange();
|
1933
2047
|
return agent.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text;
|
1934
2048
|
};
|
2049
|
+
|
2050
|
+
/**
|
2051
|
+
* returns range for word before cursor
|
2052
|
+
*
|
2053
|
+
* @param {Boolean} [findAfter] - find after cursor, default: false
|
2054
|
+
* @return {WrappedRange}
|
2055
|
+
*/
|
2056
|
+
this.getWordRange = function (findAfter) {
|
2057
|
+
var endPoint = this.getEndPoint();
|
2058
|
+
|
2059
|
+
if (!dom.isCharPoint(endPoint)) {
|
2060
|
+
return this;
|
2061
|
+
}
|
2062
|
+
|
2063
|
+
var startPoint = dom.prevPointUntil(endPoint, function (point) {
|
2064
|
+
return !dom.isCharPoint(point);
|
2065
|
+
});
|
2066
|
+
|
2067
|
+
if (findAfter) {
|
2068
|
+
endPoint = dom.nextPointUntil(endPoint, function (point) {
|
2069
|
+
return !dom.isCharPoint(point);
|
2070
|
+
});
|
2071
|
+
}
|
2072
|
+
|
2073
|
+
return new WrappedRange(
|
2074
|
+
startPoint.node,
|
2075
|
+
startPoint.offset,
|
2076
|
+
endPoint.node,
|
2077
|
+
endPoint.offset
|
2078
|
+
);
|
2079
|
+
};
|
1935
2080
|
|
1936
2081
|
/**
|
1937
2082
|
* create offsetPath bookmark
|
@@ -2116,13 +2261,13 @@
|
|
2116
2261
|
})();
|
2117
2262
|
|
2118
2263
|
/**
|
2119
|
-
* @class
|
2264
|
+
* @class defaults
|
2120
2265
|
*
|
2121
2266
|
* @singleton
|
2122
2267
|
*/
|
2123
|
-
var
|
2268
|
+
var defaults = {
|
2124
2269
|
/** @property */
|
2125
|
-
version: '0.6.
|
2270
|
+
version: '0.6.5',
|
2126
2271
|
|
2127
2272
|
/**
|
2128
2273
|
*
|
@@ -2169,6 +2314,8 @@
|
|
2169
2314
|
placeholder: false, // enable placeholder text
|
2170
2315
|
prettifyHtml: true, // enable prettifying html while toggling codeview
|
2171
2316
|
|
2317
|
+
iconPrefix: 'fa fa-', // prefix for css icon classes
|
2318
|
+
|
2172
2319
|
codemirror: { // codemirror options
|
2173
2320
|
mode: 'text/html',
|
2174
2321
|
htmlMode: true,
|
@@ -2183,7 +2330,9 @@
|
|
2183
2330
|
toolbar: [
|
2184
2331
|
['style', ['style']],
|
2185
2332
|
['font', ['bold', 'italic', 'underline', 'clear']],
|
2333
|
+
// ['font', ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'clear']],
|
2186
2334
|
['fontname', ['fontname']],
|
2335
|
+
// ['fontsize', ['fontsize']],
|
2187
2336
|
['color', ['color']],
|
2188
2337
|
['para', ['ul', 'ol', 'paragraph']],
|
2189
2338
|
['height', ['height']],
|
@@ -2223,11 +2372,13 @@
|
|
2223
2372
|
// fontName
|
2224
2373
|
fontNames: [
|
2225
2374
|
'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',
|
2226
|
-
'Helvetica Neue', 'Impact', 'Lucida Grande',
|
2375
|
+
'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',
|
2227
2376
|
'Tahoma', 'Times New Roman', 'Verdana'
|
2228
2377
|
],
|
2229
2378
|
fontNamesIgnoreCheck: [],
|
2230
2379
|
|
2380
|
+
fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],
|
2381
|
+
|
2231
2382
|
// pallete colors(n x n)
|
2232
2383
|
colors: [
|
2233
2384
|
['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],
|
@@ -2352,7 +2503,11 @@
|
|
2352
2503
|
underline: 'Underline',
|
2353
2504
|
clear: 'Remove Font Style',
|
2354
2505
|
height: 'Line Height',
|
2355
|
-
name: 'Font Family'
|
2506
|
+
name: 'Font Family',
|
2507
|
+
strikethrough: 'Strikethrough',
|
2508
|
+
subscript: 'Subscript',
|
2509
|
+
superscript: 'Superscript',
|
2510
|
+
size: 'Font Size'
|
2356
2511
|
},
|
2357
2512
|
image: {
|
2358
2513
|
image: 'Picture',
|
@@ -2520,55 +2675,128 @@
|
|
2520
2675
|
* @singleton
|
2521
2676
|
* @alternateClassName key
|
2522
2677
|
*/
|
2523
|
-
var key = {
|
2678
|
+
var key = (function () {
|
2679
|
+
var keyMap = {
|
2680
|
+
'BACKSPACE': 8,
|
2681
|
+
'TAB': 9,
|
2682
|
+
'ENTER': 13,
|
2683
|
+
'SPACE': 32,
|
2684
|
+
|
2685
|
+
// Number: 0-9
|
2686
|
+
'NUM0': 48,
|
2687
|
+
'NUM1': 49,
|
2688
|
+
'NUM2': 50,
|
2689
|
+
'NUM3': 51,
|
2690
|
+
'NUM4': 52,
|
2691
|
+
'NUM5': 53,
|
2692
|
+
'NUM6': 54,
|
2693
|
+
'NUM7': 55,
|
2694
|
+
'NUM8': 56,
|
2695
|
+
|
2696
|
+
// Alphabet: a-z
|
2697
|
+
'B': 66,
|
2698
|
+
'E': 69,
|
2699
|
+
'I': 73,
|
2700
|
+
'J': 74,
|
2701
|
+
'K': 75,
|
2702
|
+
'L': 76,
|
2703
|
+
'R': 82,
|
2704
|
+
'S': 83,
|
2705
|
+
'U': 85,
|
2706
|
+
'Y': 89,
|
2707
|
+
'Z': 90,
|
2708
|
+
|
2709
|
+
'SLASH': 191,
|
2710
|
+
'LEFTBRACKET': 219,
|
2711
|
+
'BACKSLASH': 220,
|
2712
|
+
'RIGHTBRACKET': 221
|
2713
|
+
};
|
2714
|
+
|
2715
|
+
return {
|
2716
|
+
/**
|
2717
|
+
* @method isEdit
|
2718
|
+
*
|
2719
|
+
* @param {Number} keyCode
|
2720
|
+
* @return {Boolean}
|
2721
|
+
*/
|
2722
|
+
isEdit: function (keyCode) {
|
2723
|
+
return list.contains([8, 9, 13, 32], keyCode);
|
2724
|
+
},
|
2725
|
+
/**
|
2726
|
+
* @property {Object} nameFromCode
|
2727
|
+
* @property {String} nameFromCode.8 "BACKSPACE"
|
2728
|
+
*/
|
2729
|
+
nameFromCode: func.invertObject(keyMap),
|
2730
|
+
code: keyMap
|
2731
|
+
};
|
2732
|
+
})();
|
2733
|
+
|
2734
|
+
/**
|
2735
|
+
* @class editing.History
|
2736
|
+
*
|
2737
|
+
* Editor History
|
2738
|
+
*
|
2739
|
+
*/
|
2740
|
+
var History = function ($editable) {
|
2741
|
+
var stack = [], stackOffset = -1;
|
2742
|
+
var editable = $editable[0];
|
2743
|
+
|
2744
|
+
var makeSnapshot = function () {
|
2745
|
+
var rng = range.create();
|
2746
|
+
var emptyBookmark = {s: {path: [], offset: 0}, e: {path: [], offset: 0}};
|
2747
|
+
|
2748
|
+
return {
|
2749
|
+
contents: $editable.html(),
|
2750
|
+
bookmark: (rng ? rng.bookmark(editable) : emptyBookmark)
|
2751
|
+
};
|
2752
|
+
};
|
2753
|
+
|
2754
|
+
var applySnapshot = function (snapshot) {
|
2755
|
+
if (snapshot.contents !== null) {
|
2756
|
+
$editable.html(snapshot.contents);
|
2757
|
+
}
|
2758
|
+
if (snapshot.bookmark !== null) {
|
2759
|
+
range.createFromBookmark(editable, snapshot.bookmark).select();
|
2760
|
+
}
|
2761
|
+
};
|
2762
|
+
|
2524
2763
|
/**
|
2525
|
-
*
|
2526
|
-
*
|
2527
|
-
* @param {Number} keyCode
|
2528
|
-
* @return {Boolean}
|
2764
|
+
* undo
|
2529
2765
|
*/
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2766
|
+
this.undo = function () {
|
2767
|
+
if (0 < stackOffset) {
|
2768
|
+
stackOffset--;
|
2769
|
+
applySnapshot(stack[stackOffset]);
|
2770
|
+
}
|
2771
|
+
};
|
2772
|
+
|
2533
2773
|
/**
|
2534
|
-
*
|
2535
|
-
* @property {String} nameFromCode.8 "BACKSPACE"
|
2774
|
+
* redo
|
2536
2775
|
*/
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2776
|
+
this.redo = function () {
|
2777
|
+
if (stack.length - 1 > stackOffset) {
|
2778
|
+
stackOffset++;
|
2779
|
+
applySnapshot(stack[stackOffset]);
|
2780
|
+
}
|
2781
|
+
};
|
2542
2782
|
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
'52': 'NUM4',
|
2549
|
-
'53': 'NUM5',
|
2550
|
-
'54': 'NUM6',
|
2551
|
-
'55': 'NUM7',
|
2552
|
-
'56': 'NUM8',
|
2783
|
+
/**
|
2784
|
+
* recorded undo
|
2785
|
+
*/
|
2786
|
+
this.recordUndo = function () {
|
2787
|
+
stackOffset++;
|
2553
2788
|
|
2554
|
-
//
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
'90': 'Z',
|
2566
|
-
|
2567
|
-
'191': 'SLASH',
|
2568
|
-
'219': 'LEFTBRACKET',
|
2569
|
-
'220': 'BACKSLASH',
|
2570
|
-
'221': 'RIGHTBRACKET'
|
2571
|
-
}
|
2789
|
+
// Wash out stack after stackOffset
|
2790
|
+
if (stack.length > stackOffset) {
|
2791
|
+
stack = stack.slice(0, stackOffset);
|
2792
|
+
}
|
2793
|
+
|
2794
|
+
// Create new snapshot and push it to the end
|
2795
|
+
stack.push(makeSnapshot());
|
2796
|
+
};
|
2797
|
+
|
2798
|
+
// Create first undo stack
|
2799
|
+
this.recordUndo();
|
2572
2800
|
};
|
2573
2801
|
|
2574
2802
|
/**
|
@@ -2581,6 +2809,7 @@
|
|
2581
2809
|
/**
|
2582
2810
|
* @method jQueryCSS
|
2583
2811
|
*
|
2812
|
+
* [workaround] for old jQuery
|
2584
2813
|
* passing an array of style properties to .css()
|
2585
2814
|
* will result in an object of property-value pairs.
|
2586
2815
|
* (compability with version < 1.9)
|
@@ -2717,160 +2946,46 @@
|
|
2717
2946
|
|
2718
2947
|
|
2719
2948
|
/**
|
2720
|
-
* @class editing.
|
2721
|
-
*
|
2722
|
-
* Typing
|
2949
|
+
* @class editing.Bullet
|
2723
2950
|
*
|
2951
|
+
* @alternateClassName Bullet
|
2724
2952
|
*/
|
2725
|
-
var
|
2726
|
-
|
2953
|
+
var Bullet = function () {
|
2727
2954
|
/**
|
2728
|
-
*
|
2955
|
+
* @method insertOrderedList
|
2729
2956
|
*
|
2730
|
-
*
|
2731
|
-
*
|
2732
|
-
* @
|
2957
|
+
* toggle ordered list
|
2958
|
+
*
|
2959
|
+
* @type command
|
2733
2960
|
*/
|
2734
|
-
this.
|
2735
|
-
|
2736
|
-
rng = rng.deleteContents();
|
2737
|
-
rng.insertNode(tab, true);
|
2738
|
-
|
2739
|
-
rng = range.create(tab, tabsize);
|
2740
|
-
rng.select();
|
2961
|
+
this.insertOrderedList = function () {
|
2962
|
+
this.toggleList('OL');
|
2741
2963
|
};
|
2742
2964
|
|
2743
2965
|
/**
|
2744
|
-
*
|
2966
|
+
* @method insertUnorderedList
|
2967
|
+
*
|
2968
|
+
* toggle unordered list
|
2969
|
+
*
|
2970
|
+
* @type command
|
2745
2971
|
*/
|
2746
|
-
this.
|
2747
|
-
|
2748
|
-
|
2749
|
-
// deleteContents on range.
|
2750
|
-
rng = rng.deleteContents();
|
2972
|
+
this.insertUnorderedList = function () {
|
2973
|
+
this.toggleList('UL');
|
2974
|
+
};
|
2751
2975
|
|
2752
|
-
|
2753
|
-
|
2976
|
+
/**
|
2977
|
+
* @method indent
|
2978
|
+
*
|
2979
|
+
* indent
|
2980
|
+
*
|
2981
|
+
* @type command
|
2982
|
+
*/
|
2983
|
+
this.indent = function () {
|
2984
|
+
var self = this;
|
2985
|
+
var rng = range.create().wrapBodyInlineWithPara();
|
2754
2986
|
|
2755
|
-
|
2756
|
-
var
|
2757
|
-
|
2758
|
-
var nextPara;
|
2759
|
-
// on paragraph: split paragraph
|
2760
|
-
if (splitRoot) {
|
2761
|
-
nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
|
2762
|
-
|
2763
|
-
var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
|
2764
|
-
emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
|
2765
|
-
|
2766
|
-
$.each(emptyAnchors, function (idx, anchor) {
|
2767
|
-
dom.remove(anchor);
|
2768
|
-
});
|
2769
|
-
// no paragraph: insert empty paragraph
|
2770
|
-
} else {
|
2771
|
-
var next = rng.sc.childNodes[rng.so];
|
2772
|
-
nextPara = $(dom.emptyPara)[0];
|
2773
|
-
if (next) {
|
2774
|
-
rng.sc.insertBefore(nextPara, next);
|
2775
|
-
} else {
|
2776
|
-
rng.sc.appendChild(nextPara);
|
2777
|
-
}
|
2778
|
-
}
|
2779
|
-
|
2780
|
-
range.create(nextPara, 0).normalize().select();
|
2781
|
-
};
|
2782
|
-
|
2783
|
-
};
|
2784
|
-
|
2785
|
-
/**
|
2786
|
-
* @class editing.Table
|
2787
|
-
*
|
2788
|
-
* Table
|
2789
|
-
*
|
2790
|
-
*/
|
2791
|
-
var Table = function () {
|
2792
|
-
/**
|
2793
|
-
* handle tab key
|
2794
|
-
*
|
2795
|
-
* @param {WrappedRange} rng
|
2796
|
-
* @param {Boolean} isShift
|
2797
|
-
*/
|
2798
|
-
this.tab = function (rng, isShift) {
|
2799
|
-
var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
|
2800
|
-
var table = dom.ancestor(cell, dom.isTable);
|
2801
|
-
var cells = dom.listDescendant(table, dom.isCell);
|
2802
|
-
|
2803
|
-
var nextCell = list[isShift ? 'prev' : 'next'](cells, cell);
|
2804
|
-
if (nextCell) {
|
2805
|
-
range.create(nextCell, 0).select();
|
2806
|
-
}
|
2807
|
-
};
|
2808
|
-
|
2809
|
-
/**
|
2810
|
-
* create empty table element
|
2811
|
-
*
|
2812
|
-
* @param {Number} rowCount
|
2813
|
-
* @param {Number} colCount
|
2814
|
-
* @return {Node}
|
2815
|
-
*/
|
2816
|
-
this.createTable = function (colCount, rowCount) {
|
2817
|
-
var tds = [], tdHTML;
|
2818
|
-
for (var idxCol = 0; idxCol < colCount; idxCol++) {
|
2819
|
-
tds.push('<td>' + dom.blank + '</td>');
|
2820
|
-
}
|
2821
|
-
tdHTML = tds.join('');
|
2822
|
-
|
2823
|
-
var trs = [], trHTML;
|
2824
|
-
for (var idxRow = 0; idxRow < rowCount; idxRow++) {
|
2825
|
-
trs.push('<tr>' + tdHTML + '</tr>');
|
2826
|
-
}
|
2827
|
-
trHTML = trs.join('');
|
2828
|
-
return $('<table class="table table-bordered">' + trHTML + '</table>')[0];
|
2829
|
-
};
|
2830
|
-
};
|
2831
|
-
|
2832
|
-
|
2833
|
-
/**
|
2834
|
-
* @class editing.Bullet
|
2835
|
-
*
|
2836
|
-
* @alternateClassName Bullet
|
2837
|
-
*/
|
2838
|
-
var Bullet = function () {
|
2839
|
-
/**
|
2840
|
-
* @method insertOrderedList
|
2841
|
-
*
|
2842
|
-
* toggle ordered list
|
2843
|
-
*
|
2844
|
-
* @type command
|
2845
|
-
*/
|
2846
|
-
this.insertOrderedList = function () {
|
2847
|
-
this.toggleList('OL');
|
2848
|
-
};
|
2849
|
-
|
2850
|
-
/**
|
2851
|
-
* @method insertUnorderedList
|
2852
|
-
*
|
2853
|
-
* toggle unordered list
|
2854
|
-
*
|
2855
|
-
* @type command
|
2856
|
-
*/
|
2857
|
-
this.insertUnorderedList = function () {
|
2858
|
-
this.toggleList('UL');
|
2859
|
-
};
|
2860
|
-
|
2861
|
-
/**
|
2862
|
-
* @method indent
|
2863
|
-
*
|
2864
|
-
* indent
|
2865
|
-
*
|
2866
|
-
* @type command
|
2867
|
-
*/
|
2868
|
-
this.indent = function () {
|
2869
|
-
var self = this;
|
2870
|
-
var rng = range.create().wrapBodyInlineWithPara();
|
2871
|
-
|
2872
|
-
var paras = rng.nodes(dom.isPara, { includeAncestor: true });
|
2873
|
-
var clustereds = list.clusterBy(paras, func.peq2('parentNode'));
|
2987
|
+
var paras = rng.nodes(dom.isPara, { includeAncestor: true });
|
2988
|
+
var clustereds = list.clusterBy(paras, func.peq2('parentNode'));
|
2874
2989
|
|
2875
2990
|
$.each(clustereds, function (idx, paras) {
|
2876
2991
|
var head = list.head(paras);
|
@@ -3012,12 +3127,16 @@
|
|
3012
3127
|
var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, {
|
3013
3128
|
node: last.parentNode,
|
3014
3129
|
offset: dom.position(last) + 1
|
3015
|
-
},
|
3130
|
+
}, {
|
3131
|
+
isSkipPaddingBlankHTML: true
|
3132
|
+
}) : null;
|
3016
3133
|
|
3017
3134
|
var middleList = dom.splitTree(headList, {
|
3018
3135
|
node: head.parentNode,
|
3019
3136
|
offset: dom.position(head)
|
3020
|
-
},
|
3137
|
+
}, {
|
3138
|
+
isSkipPaddingBlankHTML: true
|
3139
|
+
});
|
3021
3140
|
|
3022
3141
|
paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi) :
|
3023
3142
|
list.from(middleList.childNodes).filter(dom.isLi);
|
@@ -3051,13 +3170,139 @@
|
|
3051
3170
|
};
|
3052
3171
|
};
|
3053
3172
|
|
3173
|
+
|
3174
|
+
/**
|
3175
|
+
* @class editing.Typing
|
3176
|
+
*
|
3177
|
+
* Typing
|
3178
|
+
*
|
3179
|
+
*/
|
3180
|
+
var Typing = function () {
|
3181
|
+
|
3182
|
+
// a Bullet instance to toggle lists off
|
3183
|
+
var bullet = new Bullet();
|
3184
|
+
|
3185
|
+
/**
|
3186
|
+
* insert tab
|
3187
|
+
*
|
3188
|
+
* @param {jQuery} $editable
|
3189
|
+
* @param {WrappedRange} rng
|
3190
|
+
* @param {Number} tabsize
|
3191
|
+
*/
|
3192
|
+
this.insertTab = function ($editable, rng, tabsize) {
|
3193
|
+
var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));
|
3194
|
+
rng = rng.deleteContents();
|
3195
|
+
rng.insertNode(tab, true);
|
3196
|
+
|
3197
|
+
rng = range.create(tab, tabsize);
|
3198
|
+
rng.select();
|
3199
|
+
};
|
3200
|
+
|
3201
|
+
/**
|
3202
|
+
* insert paragraph
|
3203
|
+
*/
|
3204
|
+
this.insertParagraph = function () {
|
3205
|
+
var rng = range.create();
|
3206
|
+
|
3207
|
+
// deleteContents on range.
|
3208
|
+
rng = rng.deleteContents();
|
3209
|
+
|
3210
|
+
// Wrap range if it needs to be wrapped by paragraph
|
3211
|
+
rng = rng.wrapBodyInlineWithPara();
|
3212
|
+
|
3213
|
+
// finding paragraph
|
3214
|
+
var splitRoot = dom.ancestor(rng.sc, dom.isPara);
|
3215
|
+
|
3216
|
+
var nextPara;
|
3217
|
+
// on paragraph: split paragraph
|
3218
|
+
if (splitRoot) {
|
3219
|
+
// if it is an empty line with li
|
3220
|
+
if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) {
|
3221
|
+
// disable UL/OL and escape!
|
3222
|
+
bullet.toggleList(splitRoot.parentNode.nodeName);
|
3223
|
+
return;
|
3224
|
+
// if new line has content (not a line break)
|
3225
|
+
} else {
|
3226
|
+
nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
|
3227
|
+
|
3228
|
+
var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
|
3229
|
+
emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
|
3230
|
+
|
3231
|
+
$.each(emptyAnchors, function (idx, anchor) {
|
3232
|
+
dom.remove(anchor);
|
3233
|
+
});
|
3234
|
+
}
|
3235
|
+
// no paragraph: insert empty paragraph
|
3236
|
+
} else {
|
3237
|
+
var next = rng.sc.childNodes[rng.so];
|
3238
|
+
nextPara = $(dom.emptyPara)[0];
|
3239
|
+
if (next) {
|
3240
|
+
rng.sc.insertBefore(nextPara, next);
|
3241
|
+
} else {
|
3242
|
+
rng.sc.appendChild(nextPara);
|
3243
|
+
}
|
3244
|
+
}
|
3245
|
+
|
3246
|
+
range.create(nextPara, 0).normalize().select().focus().scrollIntoView();
|
3247
|
+
|
3248
|
+
};
|
3249
|
+
|
3250
|
+
};
|
3251
|
+
|
3252
|
+
/**
|
3253
|
+
* @class editing.Table
|
3254
|
+
*
|
3255
|
+
* Table
|
3256
|
+
*
|
3257
|
+
*/
|
3258
|
+
var Table = function () {
|
3259
|
+
/**
|
3260
|
+
* handle tab key
|
3261
|
+
*
|
3262
|
+
* @param {WrappedRange} rng
|
3263
|
+
* @param {Boolean} isShift
|
3264
|
+
*/
|
3265
|
+
this.tab = function (rng, isShift) {
|
3266
|
+
var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
|
3267
|
+
var table = dom.ancestor(cell, dom.isTable);
|
3268
|
+
var cells = dom.listDescendant(table, dom.isCell);
|
3269
|
+
|
3270
|
+
var nextCell = list[isShift ? 'prev' : 'next'](cells, cell);
|
3271
|
+
if (nextCell) {
|
3272
|
+
range.create(nextCell, 0).select();
|
3273
|
+
}
|
3274
|
+
};
|
3275
|
+
|
3276
|
+
/**
|
3277
|
+
* create empty table element
|
3278
|
+
*
|
3279
|
+
* @param {Number} rowCount
|
3280
|
+
* @param {Number} colCount
|
3281
|
+
* @return {Node}
|
3282
|
+
*/
|
3283
|
+
this.createTable = function (colCount, rowCount) {
|
3284
|
+
var tds = [], tdHTML;
|
3285
|
+
for (var idxCol = 0; idxCol < colCount; idxCol++) {
|
3286
|
+
tds.push('<td>' + dom.blank + '</td>');
|
3287
|
+
}
|
3288
|
+
tdHTML = tds.join('');
|
3289
|
+
|
3290
|
+
var trs = [], trHTML;
|
3291
|
+
for (var idxRow = 0; idxRow < rowCount; idxRow++) {
|
3292
|
+
trs.push('<tr>' + tdHTML + '</tr>');
|
3293
|
+
}
|
3294
|
+
trHTML = trs.join('');
|
3295
|
+
return $('<table class="table table-bordered">' + trHTML + '</table>')[0];
|
3296
|
+
};
|
3297
|
+
};
|
3298
|
+
|
3054
3299
|
/**
|
3055
3300
|
* @class editing.Editor
|
3056
3301
|
*
|
3057
3302
|
* Editor
|
3058
3303
|
*
|
3059
3304
|
*/
|
3060
|
-
var Editor = function () {
|
3305
|
+
var Editor = function (handler) {
|
3061
3306
|
|
3062
3307
|
var style = new Style();
|
3063
3308
|
var table = new Table();
|
@@ -3151,18 +3396,18 @@
|
|
3151
3396
|
return rng ? rng.isOnEditable() && style.current(rng, target) : false;
|
3152
3397
|
};
|
3153
3398
|
|
3154
|
-
var triggerOnBeforeChange =
|
3155
|
-
|
3156
|
-
|
3157
|
-
|
3158
|
-
|
3399
|
+
var triggerOnBeforeChange = function ($editable) {
|
3400
|
+
// TODO find holder
|
3401
|
+
handler.bindCustomEvent(
|
3402
|
+
$(), $editable.data('callbacks'), 'before.command'
|
3403
|
+
).call($editable.html(), $editable);
|
3159
3404
|
};
|
3160
3405
|
|
3161
|
-
var triggerOnChange =
|
3162
|
-
|
3163
|
-
|
3164
|
-
|
3165
|
-
|
3406
|
+
var triggerOnChange = function ($editable) {
|
3407
|
+
// TODO find holder
|
3408
|
+
handler.bindCustomEvent(
|
3409
|
+
$(), $editable.data('callbacks'), 'change'
|
3410
|
+
).call($editable.html(), $editable);
|
3166
3411
|
};
|
3167
3412
|
|
3168
3413
|
/**
|
@@ -3200,10 +3445,13 @@
|
|
3200
3445
|
* @method afterCommand
|
3201
3446
|
* after command
|
3202
3447
|
* @param {jQuery} $editable
|
3448
|
+
* @param {Boolean} isPreventTrigger
|
3203
3449
|
*/
|
3204
|
-
var afterCommand = this.afterCommand = function ($editable) {
|
3450
|
+
var afterCommand = this.afterCommand = function ($editable, isPreventTrigger) {
|
3205
3451
|
$editable.data('NoteHistory').recordUndo();
|
3206
|
-
|
3452
|
+
if (!isPreventTrigger) {
|
3453
|
+
triggerOnChange($editable);
|
3454
|
+
}
|
3207
3455
|
};
|
3208
3456
|
|
3209
3457
|
/**
|
@@ -3304,6 +3552,9 @@
|
|
3304
3552
|
|
3305
3553
|
/**
|
3306
3554
|
* @method fontName
|
3555
|
+
*
|
3556
|
+
* change font name
|
3557
|
+
*
|
3307
3558
|
* @param {jQuery} $editable
|
3308
3559
|
* @param {Mixed} value
|
3309
3560
|
*/
|
@@ -3322,7 +3573,7 @@
|
|
3322
3573
|
|
3323
3574
|
document.execCommand(sCmd, false, value);
|
3324
3575
|
|
3325
|
-
afterCommand($editable);
|
3576
|
+
afterCommand($editable, true);
|
3326
3577
|
};
|
3327
3578
|
})(commands[idx]);
|
3328
3579
|
}
|
@@ -3462,6 +3713,19 @@
|
|
3462
3713
|
afterCommand($editable);
|
3463
3714
|
};
|
3464
3715
|
|
3716
|
+
/**
|
3717
|
+
* paste HTML
|
3718
|
+
* @param {Node} $editable
|
3719
|
+
* @param {String} markup
|
3720
|
+
*/
|
3721
|
+
this.pasteHTML = function ($editable, markup) {
|
3722
|
+
beforeCommand($editable);
|
3723
|
+
var rng = this.createRange($editable);
|
3724
|
+
var contents = rng.pasteHTML(markup);
|
3725
|
+
range.createFromNode(list.last(contents)).collapse().select();
|
3726
|
+
afterCommand($editable);
|
3727
|
+
};
|
3728
|
+
|
3465
3729
|
/**
|
3466
3730
|
* formatBlock
|
3467
3731
|
*
|
@@ -3470,6 +3734,7 @@
|
|
3470
3734
|
*/
|
3471
3735
|
this.formatBlock = function ($editable, tagName) {
|
3472
3736
|
beforeCommand($editable);
|
3737
|
+
// [workaround] for MSIE, IE need `<`
|
3473
3738
|
tagName = agent.isMSIE ? '<' + tagName + '>' : tagName;
|
3474
3739
|
document.execCommand('FormatBlock', false, tagName);
|
3475
3740
|
afterCommand($editable);
|
@@ -3492,8 +3757,7 @@
|
|
3492
3757
|
/* jshint ignore:end */
|
3493
3758
|
|
3494
3759
|
/**
|
3495
|
-
*
|
3496
|
-
* FIXME: Still buggy
|
3760
|
+
* fontSize
|
3497
3761
|
*
|
3498
3762
|
* @param {jQuery} $editable
|
3499
3763
|
* @param {String} value - px
|
@@ -3501,16 +3765,13 @@
|
|
3501
3765
|
this.fontSize = function ($editable, value) {
|
3502
3766
|
beforeCommand($editable);
|
3503
3767
|
|
3504
|
-
|
3505
|
-
|
3506
|
-
|
3507
|
-
$
|
3508
|
-
|
3509
|
-
|
3510
|
-
|
3511
|
-
return this.style.fontSize === 'medium';
|
3512
|
-
}).css('font-size', value + 'px');
|
3513
|
-
}
|
3768
|
+
var rng = this.createRange($editable);
|
3769
|
+
var spans = style.styleNodes(rng);
|
3770
|
+
$.each(spans, function (idx, span) {
|
3771
|
+
$(span).css({
|
3772
|
+
'font-size': value + 'px'
|
3773
|
+
});
|
3774
|
+
});
|
3514
3775
|
|
3515
3776
|
afterCommand($editable);
|
3516
3777
|
};
|
@@ -3582,10 +3843,12 @@
|
|
3582
3843
|
}
|
3583
3844
|
|
3584
3845
|
$.each(anchors, function (idx, anchor) {
|
3585
|
-
$(anchor).attr(
|
3586
|
-
|
3587
|
-
target
|
3588
|
-
}
|
3846
|
+
$(anchor).attr('href', linkUrl);
|
3847
|
+
if (isNewWindow) {
|
3848
|
+
$(anchor).attr('target', '_blank');
|
3849
|
+
} else {
|
3850
|
+
$(anchor).removeAttr('target');
|
3851
|
+
}
|
3589
3852
|
});
|
3590
3853
|
|
3591
3854
|
var startRange = range.createFromNode(list.head(anchors)).collapse(true);
|
@@ -3623,7 +3886,7 @@
|
|
3623
3886
|
return {
|
3624
3887
|
range: rng,
|
3625
3888
|
text: rng.toString(),
|
3626
|
-
isNewWindow: $anchor.length ? $anchor.attr('target') === '_blank' :
|
3889
|
+
isNewWindow: $anchor.length ? $anchor.attr('target') === '_blank' : false,
|
3627
3890
|
url: $anchor.length ? $anchor.attr('href') : ''
|
3628
3891
|
};
|
3629
3892
|
};
|
@@ -3748,81 +4011,26 @@
|
|
3748
4011
|
beforeCommand($editable);
|
3749
4012
|
$target.detach();
|
3750
4013
|
|
3751
|
-
|
3752
|
-
|
3753
|
-
|
3754
|
-
}
|
4014
|
+
handler.bindCustomEvent(
|
4015
|
+
$(), $editable.data('callbacks'), 'media.delete'
|
4016
|
+
).call($target, this.$editable);
|
3755
4017
|
|
3756
4018
|
afterCommand($editable);
|
3757
4019
|
};
|
3758
|
-
};
|
3759
|
-
|
3760
|
-
/**
|
3761
|
-
* @class editing.History
|
3762
|
-
*
|
3763
|
-
* Editor History
|
3764
|
-
*
|
3765
|
-
*/
|
3766
|
-
var History = function ($editable) {
|
3767
|
-
var stack = [], stackOffset = -1;
|
3768
|
-
var editable = $editable[0];
|
3769
|
-
|
3770
|
-
var makeSnapshot = function () {
|
3771
|
-
var rng = range.create();
|
3772
|
-
var emptyBookmark = {s: {path: [0], offset: 0}, e: {path: [0], offset: 0}};
|
3773
|
-
|
3774
|
-
return {
|
3775
|
-
contents: $editable.html(),
|
3776
|
-
bookmark: (rng ? rng.bookmark(editable) : emptyBookmark)
|
3777
|
-
};
|
3778
|
-
};
|
3779
|
-
|
3780
|
-
var applySnapshot = function (snapshot) {
|
3781
|
-
if (snapshot.contents !== null) {
|
3782
|
-
$editable.html(snapshot.contents);
|
3783
|
-
}
|
3784
|
-
if (snapshot.bookmark !== null) {
|
3785
|
-
range.createFromBookmark(editable, snapshot.bookmark).select();
|
3786
|
-
}
|
3787
|
-
};
|
3788
|
-
|
3789
|
-
/**
|
3790
|
-
* undo
|
3791
|
-
*/
|
3792
|
-
this.undo = function () {
|
3793
|
-
if (0 < stackOffset) {
|
3794
|
-
stackOffset--;
|
3795
|
-
applySnapshot(stack[stackOffset]);
|
3796
|
-
}
|
3797
|
-
};
|
3798
|
-
|
3799
|
-
/**
|
3800
|
-
* redo
|
3801
|
-
*/
|
3802
|
-
this.redo = function () {
|
3803
|
-
if (stack.length - 1 > stackOffset) {
|
3804
|
-
stackOffset++;
|
3805
|
-
applySnapshot(stack[stackOffset]);
|
3806
|
-
}
|
3807
|
-
};
|
3808
4020
|
|
3809
4021
|
/**
|
3810
|
-
*
|
4022
|
+
* set focus
|
4023
|
+
*
|
4024
|
+
* @param $editable
|
3811
4025
|
*/
|
3812
|
-
this.
|
3813
|
-
|
4026
|
+
this.focus = function ($editable) {
|
4027
|
+
$editable.focus();
|
3814
4028
|
|
3815
|
-
//
|
3816
|
-
if (
|
3817
|
-
|
4029
|
+
// [workaround] for firefox bug http://goo.gl/lVfAaI
|
4030
|
+
if (agent.isFF) {
|
4031
|
+
range.createFromNode($editable[0].firstChild || $editable[0]).collapse().select();
|
3818
4032
|
}
|
3819
|
-
|
3820
|
-
// Create new snapshot and push it to the end
|
3821
|
-
stack.push(makeSnapshot());
|
3822
4033
|
};
|
3823
|
-
|
3824
|
-
// Create first undo stack
|
3825
|
-
this.recordUndo();
|
3826
4034
|
};
|
3827
4035
|
|
3828
4036
|
/**
|
@@ -3908,10 +4116,18 @@
|
|
3908
4116
|
if ($fontname.length) {
|
3909
4117
|
var selectedFont = styleInfo['font-family'];
|
3910
4118
|
if (!!selectedFont) {
|
3911
|
-
|
3912
|
-
|
4119
|
+
|
4120
|
+
var list = selectedFont.split(',');
|
4121
|
+
for (var i = 0, len = list.length; i < len; i++) {
|
4122
|
+
selectedFont = list[i].replace(/[\'\"]/g, '').replace(/\s+$/, '').replace(/^\s+/, '');
|
4123
|
+
if (agent.isFontInstalled(selectedFont)) {
|
4124
|
+
break;
|
4125
|
+
}
|
4126
|
+
}
|
4127
|
+
|
3913
4128
|
$fontname.find('.note-current-fontname').text(selectedFont);
|
3914
4129
|
checkDropdownMenu($fontname, selectedFont);
|
4130
|
+
|
3915
4131
|
}
|
3916
4132
|
}
|
3917
4133
|
|
@@ -4022,7 +4238,6 @@
|
|
4022
4238
|
};
|
4023
4239
|
|
4024
4240
|
/**
|
4025
|
-
*
|
4026
4241
|
* @param {jQuery} $container
|
4027
4242
|
* @param {Boolean} [bFullscreen=false]
|
4028
4243
|
*/
|
@@ -4032,13 +4247,83 @@
|
|
4032
4247
|
};
|
4033
4248
|
|
4034
4249
|
/**
|
4035
|
-
*
|
4036
4250
|
* @param {jQuery} $container
|
4037
4251
|
* @param {Boolean} [isCodeview=false]
|
4038
4252
|
*/
|
4039
4253
|
this.updateCodeview = function ($container, isCodeview) {
|
4040
4254
|
var $btn = $container.find('button[data-event="codeview"]');
|
4041
4255
|
$btn.toggleClass('active', isCodeview);
|
4256
|
+
|
4257
|
+
if (isCodeview) {
|
4258
|
+
this.deactivate($container);
|
4259
|
+
} else {
|
4260
|
+
this.activate($container);
|
4261
|
+
}
|
4262
|
+
};
|
4263
|
+
|
4264
|
+
/**
|
4265
|
+
* get button in toolbar
|
4266
|
+
*
|
4267
|
+
* @param {jQuery} $editable
|
4268
|
+
* @param {String} name
|
4269
|
+
* @return {jQuery}
|
4270
|
+
*/
|
4271
|
+
this.get = function ($editable, name) {
|
4272
|
+
var $toolbar = dom.makeLayoutInfo($editable).toolbar();
|
4273
|
+
|
4274
|
+
return $toolbar.find('[data-name=' + name + ']');
|
4275
|
+
};
|
4276
|
+
|
4277
|
+
/**
|
4278
|
+
* set button state
|
4279
|
+
* @param {jQuery} $editable
|
4280
|
+
* @param {String} name
|
4281
|
+
* @param {Boolean} [isActive=true]
|
4282
|
+
*/
|
4283
|
+
this.setButtonState = function ($editable, name, isActive) {
|
4284
|
+
isActive = (isActive === false) ? false : true;
|
4285
|
+
|
4286
|
+
var $button = this.get($editable, name);
|
4287
|
+
$button.toggleClass('active', isActive);
|
4288
|
+
};
|
4289
|
+
};
|
4290
|
+
|
4291
|
+
var EDITABLE_PADDING = 24;
|
4292
|
+
|
4293
|
+
var Statusbar = function () {
|
4294
|
+
var $document = $(document);
|
4295
|
+
|
4296
|
+
this.attach = function (layoutInfo, options) {
|
4297
|
+
if (!options.disableResizeEditor) {
|
4298
|
+
layoutInfo.statusbar().on('mousedown', hStatusbarMousedown);
|
4299
|
+
}
|
4300
|
+
};
|
4301
|
+
|
4302
|
+
/**
|
4303
|
+
* `mousedown` event handler on statusbar
|
4304
|
+
*
|
4305
|
+
* @param {MouseEvent} event
|
4306
|
+
*/
|
4307
|
+
var hStatusbarMousedown = function (event) {
|
4308
|
+
event.preventDefault();
|
4309
|
+
event.stopPropagation();
|
4310
|
+
|
4311
|
+
var $editable = dom.makeLayoutInfo(event.target).editable();
|
4312
|
+
var editableTop = $editable.offset().top - $document.scrollTop();
|
4313
|
+
|
4314
|
+
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
|
4315
|
+
var options = layoutInfo.editor().data('options');
|
4316
|
+
|
4317
|
+
$document.on('mousemove', function (event) {
|
4318
|
+
var nHeight = event.clientY - (editableTop + EDITABLE_PADDING);
|
4319
|
+
|
4320
|
+
nHeight = (options.minHeight > 0) ? Math.max(nHeight, options.minHeight) : nHeight;
|
4321
|
+
nHeight = (options.maxHeight > 0) ? Math.min(nHeight, options.maxHeight) : nHeight;
|
4322
|
+
|
4323
|
+
$editable.height(nHeight);
|
4324
|
+
}).one('mouseup', function () {
|
4325
|
+
$document.off('mousemove');
|
4326
|
+
});
|
4042
4327
|
};
|
4043
4328
|
};
|
4044
4329
|
|
@@ -4103,7 +4388,13 @@
|
|
4103
4388
|
if (styleInfo.anchor) {
|
4104
4389
|
var $anchor = $linkPopover.find('a');
|
4105
4390
|
var href = $(styleInfo.anchor).attr('href');
|
4391
|
+
var target = $(styleInfo.anchor).attr('target');
|
4106
4392
|
$anchor.attr('href', href).html(href);
|
4393
|
+
if (!target) {
|
4394
|
+
$anchor.removeAttr('target');
|
4395
|
+
} else {
|
4396
|
+
$anchor.attr('target', '_blank');
|
4397
|
+
}
|
4107
4398
|
showPopover($linkPopover, posFromPlaceholder(styleInfo.anchor, isAirMode));
|
4108
4399
|
} else {
|
4109
4400
|
$linkPopover.hide();
|
@@ -4154,7 +4445,55 @@
|
|
4154
4445
|
*
|
4155
4446
|
* Handle
|
4156
4447
|
*/
|
4157
|
-
var Handle = function () {
|
4448
|
+
var Handle = function (handler) {
|
4449
|
+
var $document = $(document);
|
4450
|
+
|
4451
|
+
/**
|
4452
|
+
* `mousedown` event handler on $handle
|
4453
|
+
* - controlSizing: resize image
|
4454
|
+
*
|
4455
|
+
* @param {MouseEvent} event
|
4456
|
+
*/
|
4457
|
+
var hHandleMousedown = function (event) {
|
4458
|
+
if (dom.isControlSizing(event.target)) {
|
4459
|
+
event.preventDefault();
|
4460
|
+
event.stopPropagation();
|
4461
|
+
|
4462
|
+
var layoutInfo = dom.makeLayoutInfo(event.target),
|
4463
|
+
$handle = layoutInfo.handle(),
|
4464
|
+
$popover = layoutInfo.popover(),
|
4465
|
+
$editable = layoutInfo.editable(),
|
4466
|
+
$editor = layoutInfo.editor();
|
4467
|
+
|
4468
|
+
var target = $handle.find('.note-control-selection').data('target'),
|
4469
|
+
$target = $(target), posStart = $target.offset(),
|
4470
|
+
scrollTop = $document.scrollTop();
|
4471
|
+
|
4472
|
+
var isAirMode = $editor.data('options').airMode;
|
4473
|
+
|
4474
|
+
$document.on('mousemove', function (event) {
|
4475
|
+
handler.invoke('editor.resizeTo', {
|
4476
|
+
x: event.clientX - posStart.left,
|
4477
|
+
y: event.clientY - (posStart.top - scrollTop)
|
4478
|
+
}, $target, !event.shiftKey);
|
4479
|
+
|
4480
|
+
handler.invoke('handle.update', $handle, {image: target}, isAirMode);
|
4481
|
+
handler.invoke('popover.update', $popover, {image: target}, isAirMode);
|
4482
|
+
}).one('mouseup', function () {
|
4483
|
+
$document.off('mousemove');
|
4484
|
+
handler.invoke('editor.afterCommand', $editable);
|
4485
|
+
});
|
4486
|
+
|
4487
|
+
if (!$target.data('ratio')) { // original ratio.
|
4488
|
+
$target.data('ratio', $target.height() / $target.width());
|
4489
|
+
}
|
4490
|
+
}
|
4491
|
+
};
|
4492
|
+
|
4493
|
+
this.attach = function (layoutInfo) {
|
4494
|
+
layoutInfo.handle().on('mousedown', hHandleMousedown);
|
4495
|
+
};
|
4496
|
+
|
4158
4497
|
/**
|
4159
4498
|
* update handle
|
4160
4499
|
* @param {jQuery} $handle
|
@@ -4197,97 +4536,389 @@
|
|
4197
4536
|
};
|
4198
4537
|
};
|
4199
4538
|
|
4200
|
-
|
4201
|
-
|
4202
|
-
|
4203
|
-
* Dialog
|
4204
|
-
*
|
4205
|
-
*/
|
4206
|
-
var Dialog = function () {
|
4539
|
+
var Fullscreen = function (handler) {
|
4540
|
+
var $window = $(window);
|
4541
|
+
var $scrollbar = $('html, body');
|
4207
4542
|
|
4208
4543
|
/**
|
4209
|
-
* toggle
|
4544
|
+
* toggle fullscreen
|
4210
4545
|
*
|
4211
|
-
* @
|
4212
|
-
* @param {jQuery} $btn
|
4213
|
-
* @param {Boolean} isEnable
|
4546
|
+
* @param {Object} layoutInfo
|
4214
4547
|
*/
|
4215
|
-
|
4216
|
-
$btn.toggleClass('disabled', !isEnable);
|
4217
|
-
$btn.attr('disabled', !isEnable);
|
4218
|
-
};
|
4548
|
+
this.toggle = function (layoutInfo) {
|
4219
4549
|
|
4220
|
-
|
4221
|
-
|
4222
|
-
|
4223
|
-
|
4224
|
-
|
4225
|
-
|
4226
|
-
|
4227
|
-
|
4228
|
-
|
4229
|
-
|
4550
|
+
var $editor = layoutInfo.editor(),
|
4551
|
+
$toolbar = layoutInfo.toolbar(),
|
4552
|
+
$editable = layoutInfo.editable(),
|
4553
|
+
$codable = layoutInfo.codable();
|
4554
|
+
|
4555
|
+
var resize = function (size) {
|
4556
|
+
$editable.css('height', size.h);
|
4557
|
+
$codable.css('height', size.h);
|
4558
|
+
if ($codable.data('cmeditor')) {
|
4559
|
+
$codable.data('cmeditor').setsize(null, size.h);
|
4560
|
+
}
|
4561
|
+
};
|
4230
4562
|
|
4231
|
-
|
4232
|
-
|
4233
|
-
|
4563
|
+
$editor.toggleClass('fullscreen');
|
4564
|
+
var isFullscreen = $editor.hasClass('fullscreen');
|
4565
|
+
if (isFullscreen) {
|
4566
|
+
$editable.data('orgheight', $editable.css('height'));
|
4234
4567
|
|
4235
|
-
$
|
4236
|
-
|
4237
|
-
|
4238
|
-
|
4239
|
-
|
4240
|
-
$imageDialog.modal('hide');
|
4241
|
-
})
|
4242
|
-
.val('')
|
4243
|
-
);
|
4568
|
+
$window.on('resize', function () {
|
4569
|
+
resize({
|
4570
|
+
h: $window.height() - $toolbar.outerHeight()
|
4571
|
+
});
|
4572
|
+
}).trigger('resize');
|
4244
4573
|
|
4245
|
-
|
4246
|
-
|
4574
|
+
$scrollbar.css('overflow', 'hidden');
|
4575
|
+
} else {
|
4576
|
+
$window.off('resize');
|
4577
|
+
resize({
|
4578
|
+
h: $editable.data('orgheight')
|
4579
|
+
});
|
4580
|
+
$scrollbar.css('overflow', 'visible');
|
4581
|
+
}
|
4247
4582
|
|
4248
|
-
|
4249
|
-
|
4250
|
-
|
4583
|
+
handler.invoke('toolbar.updateFullscreen', $toolbar, isFullscreen);
|
4584
|
+
};
|
4585
|
+
};
|
4251
4586
|
|
4252
|
-
$imageUrl.on('keyup paste', function (event) {
|
4253
|
-
var url;
|
4254
|
-
|
4255
|
-
if (event.type === 'paste') {
|
4256
|
-
url = event.originalEvent.clipboardData.getData('text');
|
4257
|
-
} else {
|
4258
|
-
url = $imageUrl.val();
|
4259
|
-
}
|
4260
|
-
|
4261
|
-
toggleBtn($imageBtn, url);
|
4262
|
-
}).val('').trigger('focus');
|
4263
|
-
}).one('hidden.bs.modal', function () {
|
4264
|
-
$imageInput.off('change');
|
4265
|
-
$imageUrl.off('keyup paste');
|
4266
|
-
$imageBtn.off('click');
|
4267
4587
|
|
4268
|
-
|
4269
|
-
|
4270
|
-
|
4271
|
-
|
4588
|
+
var CodeMirror;
|
4589
|
+
if (agent.hasCodeMirror) {
|
4590
|
+
if (agent.isSupportAmd) {
|
4591
|
+
require(['CodeMirror'], function (cm) {
|
4592
|
+
CodeMirror = cm;
|
4272
4593
|
});
|
4594
|
+
} else {
|
4595
|
+
CodeMirror = window.CodeMirror;
|
4596
|
+
}
|
4597
|
+
}
|
4598
|
+
|
4599
|
+
/**
|
4600
|
+
* @class Codeview
|
4601
|
+
*/
|
4602
|
+
var Codeview = function (handler) {
|
4603
|
+
|
4604
|
+
this.sync = function (layoutInfo) {
|
4605
|
+
var isCodeview = handler.invoke('codeview.isActivated', layoutInfo);
|
4606
|
+
if (isCodeview && agent.hasCodeMirror) {
|
4607
|
+
layoutInfo.codable().data('cmEditor').save();
|
4608
|
+
}
|
4273
4609
|
};
|
4274
4610
|
|
4275
4611
|
/**
|
4276
|
-
*
|
4277
|
-
*
|
4278
|
-
* @param {jQuery} $editable
|
4279
|
-
* @param {jQuery} $dialog
|
4280
|
-
* @param {Object} linkInfo
|
4281
|
-
* @return {Promise}
|
4612
|
+
* @param {Object} layoutInfo
|
4613
|
+
* @return {Boolean}
|
4282
4614
|
*/
|
4283
|
-
this.
|
4284
|
-
|
4285
|
-
|
4615
|
+
this.isActivated = function (layoutInfo) {
|
4616
|
+
var $editor = layoutInfo.editor();
|
4617
|
+
return $editor.hasClass('codeview');
|
4618
|
+
};
|
4286
4619
|
|
4287
|
-
|
4288
|
-
|
4289
|
-
|
4290
|
-
|
4620
|
+
/**
|
4621
|
+
* toggle codeview
|
4622
|
+
*
|
4623
|
+
* @param {Object} layoutInfo
|
4624
|
+
*/
|
4625
|
+
this.toggle = function (layoutInfo) {
|
4626
|
+
if (this.isActivated(layoutInfo)) {
|
4627
|
+
this.deactivate(layoutInfo);
|
4628
|
+
} else {
|
4629
|
+
this.activate(layoutInfo);
|
4630
|
+
}
|
4631
|
+
};
|
4632
|
+
|
4633
|
+
/**
|
4634
|
+
* activate code view
|
4635
|
+
*
|
4636
|
+
* @param {Object} layoutInfo
|
4637
|
+
*/
|
4638
|
+
this.activate = function (layoutInfo) {
|
4639
|
+
var $editor = layoutInfo.editor(),
|
4640
|
+
$toolbar = layoutInfo.toolbar(),
|
4641
|
+
$editable = layoutInfo.editable(),
|
4642
|
+
$codable = layoutInfo.codable(),
|
4643
|
+
$popover = layoutInfo.popover(),
|
4644
|
+
$handle = layoutInfo.handle();
|
4645
|
+
|
4646
|
+
var options = $editor.data('options');
|
4647
|
+
|
4648
|
+
$codable.val(dom.html($editable, options.prettifyHtml));
|
4649
|
+
$codable.height($editable.height());
|
4650
|
+
|
4651
|
+
handler.invoke('toolbar.updateCodeview', $toolbar, true);
|
4652
|
+
handler.invoke('popover.hide', $popover);
|
4653
|
+
handler.invoke('handle.hide', $handle);
|
4654
|
+
|
4655
|
+
$editor.addClass('codeview');
|
4656
|
+
|
4657
|
+
$codable.focus();
|
4658
|
+
|
4659
|
+
// activate CodeMirror as codable
|
4660
|
+
if (agent.hasCodeMirror) {
|
4661
|
+
var cmEditor = CodeMirror.fromTextArea($codable[0], options.codemirror);
|
4662
|
+
|
4663
|
+
// CodeMirror TernServer
|
4664
|
+
if (options.codemirror.tern) {
|
4665
|
+
var server = new CodeMirror.TernServer(options.codemirror.tern);
|
4666
|
+
cmEditor.ternServer = server;
|
4667
|
+
cmEditor.on('cursorActivity', function (cm) {
|
4668
|
+
server.updateArgHints(cm);
|
4669
|
+
});
|
4670
|
+
}
|
4671
|
+
|
4672
|
+
// CodeMirror hasn't Padding.
|
4673
|
+
cmEditor.setSize(null, $editable.outerHeight());
|
4674
|
+
$codable.data('cmEditor', cmEditor);
|
4675
|
+
}
|
4676
|
+
};
|
4677
|
+
|
4678
|
+
/**
|
4679
|
+
* deactivate code view
|
4680
|
+
*
|
4681
|
+
* @param {Object} layoutInfo
|
4682
|
+
*/
|
4683
|
+
this.deactivate = function (layoutInfo) {
|
4684
|
+
var $editor = layoutInfo.editor(),
|
4685
|
+
$toolbar = layoutInfo.toolbar(),
|
4686
|
+
$editable = layoutInfo.editable(),
|
4687
|
+
$codable = layoutInfo.codable();
|
4688
|
+
|
4689
|
+
var options = $editor.data('options');
|
4690
|
+
|
4691
|
+
// deactivate CodeMirror as codable
|
4692
|
+
if (agent.hasCodeMirror) {
|
4693
|
+
var cmEditor = $codable.data('cmEditor');
|
4694
|
+
$codable.val(cmEditor.getValue());
|
4695
|
+
cmEditor.toTextArea();
|
4696
|
+
}
|
4697
|
+
|
4698
|
+
$editable.html(dom.value($codable, options.prettifyHtml) || dom.emptyPara);
|
4699
|
+
$editable.height(options.height ? $codable.height() : 'auto');
|
4700
|
+
$editor.removeClass('codeview');
|
4701
|
+
|
4702
|
+
$editable.focus();
|
4703
|
+
|
4704
|
+
handler.invoke('toolbar.updateCodeview', $toolbar, false);
|
4705
|
+
};
|
4706
|
+
};
|
4707
|
+
|
4708
|
+
var DragAndDrop = function (handler) {
|
4709
|
+
var $document = $(document);
|
4710
|
+
|
4711
|
+
/**
|
4712
|
+
* attach Drag and Drop Events
|
4713
|
+
*
|
4714
|
+
* @param {Object} layoutInfo - layout Informations
|
4715
|
+
* @param {Object} options
|
4716
|
+
*/
|
4717
|
+
this.attach = function (layoutInfo, options) {
|
4718
|
+
if (options.airMode || options.disableDragAndDrop) {
|
4719
|
+
// prevent default drop event
|
4720
|
+
$document.on('drop', function (e) {
|
4721
|
+
e.preventDefault();
|
4722
|
+
});
|
4723
|
+
} else {
|
4724
|
+
this.attachDragAndDropEvent(layoutInfo, options);
|
4725
|
+
}
|
4726
|
+
};
|
4727
|
+
|
4728
|
+
/**
|
4729
|
+
* attach Drag and Drop Events
|
4730
|
+
*
|
4731
|
+
* @param {Object} layoutInfo - layout Informations
|
4732
|
+
* @param {Object} options
|
4733
|
+
*/
|
4734
|
+
this.attachDragAndDropEvent = function (layoutInfo, options) {
|
4735
|
+
var collection = $(),
|
4736
|
+
$editor = layoutInfo.editor(),
|
4737
|
+
$dropzone = layoutInfo.dropzone(),
|
4738
|
+
$dropzoneMessage = $dropzone.find('.note-dropzone-message');
|
4739
|
+
|
4740
|
+
// show dropzone on dragenter when dragging a object to document
|
4741
|
+
// -but only if the editor is visible, i.e. has a positive width and height
|
4742
|
+
$document.on('dragenter', function (e) {
|
4743
|
+
var isCodeview = handler.invoke('codeview.isActivated', layoutInfo);
|
4744
|
+
var hasEditorSize = $editor.width() > 0 && $editor.height() > 0;
|
4745
|
+
if (!isCodeview && !collection.length && hasEditorSize) {
|
4746
|
+
$editor.addClass('dragover');
|
4747
|
+
$dropzone.width($editor.width());
|
4748
|
+
$dropzone.height($editor.height());
|
4749
|
+
$dropzoneMessage.text(options.langInfo.image.dragImageHere);
|
4750
|
+
}
|
4751
|
+
collection = collection.add(e.target);
|
4752
|
+
}).on('dragleave', function (e) {
|
4753
|
+
collection = collection.not(e.target);
|
4754
|
+
if (!collection.length) {
|
4755
|
+
$editor.removeClass('dragover');
|
4756
|
+
}
|
4757
|
+
}).on('drop', function () {
|
4758
|
+
collection = $();
|
4759
|
+
$editor.removeClass('dragover');
|
4760
|
+
});
|
4761
|
+
|
4762
|
+
// change dropzone's message on hover.
|
4763
|
+
$dropzone.on('dragenter', function () {
|
4764
|
+
$dropzone.addClass('hover');
|
4765
|
+
$dropzoneMessage.text(options.langInfo.image.dropImage);
|
4766
|
+
}).on('dragleave', function () {
|
4767
|
+
$dropzone.removeClass('hover');
|
4768
|
+
$dropzoneMessage.text(options.langInfo.image.dragImageHere);
|
4769
|
+
});
|
4770
|
+
|
4771
|
+
// attach dropImage
|
4772
|
+
$dropzone.on('drop', function (event) {
|
4773
|
+
event.preventDefault();
|
4774
|
+
|
4775
|
+
var dataTransfer = event.originalEvent.dataTransfer;
|
4776
|
+
var html = dataTransfer.getData('text/html');
|
4777
|
+
var text = dataTransfer.getData('text/plain');
|
4778
|
+
|
4779
|
+
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
|
4780
|
+
|
4781
|
+
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
|
4782
|
+
layoutInfo.editable().focus();
|
4783
|
+
handler.insertImages(layoutInfo, dataTransfer.files);
|
4784
|
+
} else if (html) {
|
4785
|
+
$(html).each(function () {
|
4786
|
+
layoutInfo.editable().focus();
|
4787
|
+
handler.invoke('editor.insertNode', layoutInfo.editable(), this);
|
4788
|
+
});
|
4789
|
+
} else if (text) {
|
4790
|
+
layoutInfo.editable().focus();
|
4791
|
+
handler.invoke('editor.insertText', layoutInfo.editable(), text);
|
4792
|
+
}
|
4793
|
+
}).on('dragover', false); // prevent default dragover event
|
4794
|
+
};
|
4795
|
+
};
|
4796
|
+
|
4797
|
+
var Clipboard = function (handler) {
|
4798
|
+
|
4799
|
+
this.attach = function (layoutInfo) {
|
4800
|
+
layoutInfo.editable().on('paste', hPasteClipboardImage);
|
4801
|
+
};
|
4802
|
+
|
4803
|
+
/**
|
4804
|
+
* paste clipboard image
|
4805
|
+
*
|
4806
|
+
* @param {Event} event
|
4807
|
+
*/
|
4808
|
+
var hPasteClipboardImage = function (event) {
|
4809
|
+
var clipboardData = event.originalEvent.clipboardData;
|
4810
|
+
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
|
4811
|
+
var $editable = layoutInfo.editable();
|
4812
|
+
|
4813
|
+
if (!clipboardData || !clipboardData.items || !clipboardData.items.length) {
|
4814
|
+
var callbacks = $editable.data('callbacks');
|
4815
|
+
// only can run if it has onImageUpload method
|
4816
|
+
if (!callbacks.onImageUpload) {
|
4817
|
+
return;
|
4818
|
+
}
|
4819
|
+
|
4820
|
+
// save cursor
|
4821
|
+
handler.invoke('editor.saveNode', $editable);
|
4822
|
+
handler.invoke('editor.saveRange', $editable);
|
4823
|
+
|
4824
|
+
$editable.html('');
|
4825
|
+
|
4826
|
+
setTimeout(function () {
|
4827
|
+
var $img = $editable.find('img');
|
4828
|
+
|
4829
|
+
// if img is no in clipboard, insert text or dom
|
4830
|
+
if (!$img.length || $img[0].src.indexOf('data:') === -1) {
|
4831
|
+
var html = $editable.html();
|
4832
|
+
|
4833
|
+
handler.invoke('editor.restoreNode', $editable);
|
4834
|
+
handler.invoke('editor.restoreRange', $editable);
|
4835
|
+
|
4836
|
+
handler.invoke('editor.focus', $editable);
|
4837
|
+
try {
|
4838
|
+
handler.invoke('editor.pasteHTML', $editable, html);
|
4839
|
+
} catch (ex) {
|
4840
|
+
handler.invoke('editor.insertText', $editable, html);
|
4841
|
+
}
|
4842
|
+
return;
|
4843
|
+
}
|
4844
|
+
|
4845
|
+
var datauri = $img[0].src;
|
4846
|
+
|
4847
|
+
var data = atob(datauri.split(',')[1]);
|
4848
|
+
var array = new Uint8Array(data.length);
|
4849
|
+
for (var i = 0; i < data.length; i++) {
|
4850
|
+
array[i] = data.charCodeAt(i);
|
4851
|
+
}
|
4852
|
+
|
4853
|
+
var blob = new Blob([array], { type : 'image/png' });
|
4854
|
+
blob.name = 'clipboard.png';
|
4855
|
+
|
4856
|
+
handler.invoke('editor.restoreNode', $editable);
|
4857
|
+
handler.invoke('editor.restoreRange', $editable);
|
4858
|
+
handler.insertImages(layoutInfo, [blob]);
|
4859
|
+
|
4860
|
+
handler.invoke('editor.afterCommand', $editable);
|
4861
|
+
}, 0);
|
4862
|
+
|
4863
|
+
return;
|
4864
|
+
}
|
4865
|
+
|
4866
|
+
var item = list.head(clipboardData.items);
|
4867
|
+
var isClipboardImage = item.kind === 'file' && item.type.indexOf('image/') !== -1;
|
4868
|
+
|
4869
|
+
if (isClipboardImage) {
|
4870
|
+
handler.insertImages(layoutInfo, [item.getAsFile()]);
|
4871
|
+
}
|
4872
|
+
|
4873
|
+
handler.invoke('editor.afterCommand', $editable);
|
4874
|
+
};
|
4875
|
+
};
|
4876
|
+
|
4877
|
+
var LinkDialog = function (handler) {
|
4878
|
+
|
4879
|
+
/**
|
4880
|
+
* toggle button status
|
4881
|
+
*
|
4882
|
+
* @private
|
4883
|
+
* @param {jQuery} $btn
|
4884
|
+
* @param {Boolean} isEnable
|
4885
|
+
*/
|
4886
|
+
var toggleBtn = function ($btn, isEnable) {
|
4887
|
+
$btn.toggleClass('disabled', !isEnable);
|
4888
|
+
$btn.attr('disabled', !isEnable);
|
4889
|
+
};
|
4890
|
+
|
4891
|
+
/**
|
4892
|
+
* bind enter key
|
4893
|
+
*
|
4894
|
+
* @private
|
4895
|
+
* @param {jQuery} $input
|
4896
|
+
* @param {jQuery} $btn
|
4897
|
+
*/
|
4898
|
+
var bindEnterKey = function ($input, $btn) {
|
4899
|
+
$input.on('keypress', function (event) {
|
4900
|
+
if (event.keyCode === key.code.ENTER) {
|
4901
|
+
$btn.trigger('click');
|
4902
|
+
}
|
4903
|
+
});
|
4904
|
+
};
|
4905
|
+
|
4906
|
+
/**
|
4907
|
+
* Show link dialog and set event handlers on dialog controls.
|
4908
|
+
*
|
4909
|
+
* @param {jQuery} $editable
|
4910
|
+
* @param {jQuery} $dialog
|
4911
|
+
* @param {Object} linkInfo
|
4912
|
+
* @return {Promise}
|
4913
|
+
*/
|
4914
|
+
this.showLinkDialog = function ($editable, $dialog, linkInfo) {
|
4915
|
+
return $.Deferred(function (deferred) {
|
4916
|
+
var $linkDialog = $dialog.find('.note-link-dialog');
|
4917
|
+
|
4918
|
+
var $linkText = $linkDialog.find('.note-link-text'),
|
4919
|
+
$linkUrl = $linkDialog.find('.note-link-url'),
|
4920
|
+
$linkBtn = $linkDialog.find('.note-link-btn'),
|
4921
|
+
$openInNewWindow = $linkDialog.find('input[type=checkbox]');
|
4291
4922
|
|
4292
4923
|
$linkDialog.one('shown.bs.modal', function () {
|
4293
4924
|
$linkText.val(linkInfo.text);
|
@@ -4313,6 +4944,9 @@
|
|
4313
4944
|
}
|
4314
4945
|
}).val(linkInfo.url).trigger('focus').trigger('select');
|
4315
4946
|
|
4947
|
+
bindEnterKey($linkUrl, $linkBtn);
|
4948
|
+
bindEnterKey($linkText, $linkBtn);
|
4949
|
+
|
4316
4950
|
$openInNewWindow.prop('checked', linkInfo.newWindow);
|
4317
4951
|
|
4318
4952
|
$linkBtn.one('click', function (event) {
|
@@ -4328,8 +4962,8 @@
|
|
4328
4962
|
});
|
4329
4963
|
}).one('hidden.bs.modal', function () {
|
4330
4964
|
// detach events
|
4331
|
-
$linkText.off('input');
|
4332
|
-
$linkUrl.off('input');
|
4965
|
+
$linkText.off('input keypress');
|
4966
|
+
$linkUrl.off('input keypress');
|
4333
4967
|
$linkBtn.off('click');
|
4334
4968
|
|
4335
4969
|
if (deferred.state() === 'pending') {
|
@@ -4339,6 +4973,136 @@
|
|
4339
4973
|
}).promise();
|
4340
4974
|
};
|
4341
4975
|
|
4976
|
+
/**
|
4977
|
+
* @param {Object} layoutInfo
|
4978
|
+
*/
|
4979
|
+
this.show = function (layoutInfo) {
|
4980
|
+
var $editor = layoutInfo.editor(),
|
4981
|
+
$dialog = layoutInfo.dialog(),
|
4982
|
+
$editable = layoutInfo.editable(),
|
4983
|
+
$popover = layoutInfo.popover(),
|
4984
|
+
linkInfo = handler.invoke('editor.getLinkInfo', $editable);
|
4985
|
+
|
4986
|
+
var options = $editor.data('options');
|
4987
|
+
|
4988
|
+
handler.invoke('editor.saveRange', $editable);
|
4989
|
+
this.showLinkDialog($editable, $dialog, linkInfo).then(function (linkInfo) {
|
4990
|
+
handler.invoke('editor.restoreRange', $editable);
|
4991
|
+
handler.invoke('editor.createLink', $editable, linkInfo, options);
|
4992
|
+
// hide popover after creating link
|
4993
|
+
handler.invoke('popover.hide', $popover);
|
4994
|
+
}).fail(function () {
|
4995
|
+
handler.invoke('editor.restoreRange', $editable);
|
4996
|
+
});
|
4997
|
+
};
|
4998
|
+
};
|
4999
|
+
|
5000
|
+
var ImageDialog = function (handler) {
|
5001
|
+
/**
|
5002
|
+
* toggle button status
|
5003
|
+
*
|
5004
|
+
* @private
|
5005
|
+
* @param {jQuery} $btn
|
5006
|
+
* @param {Boolean} isEnable
|
5007
|
+
*/
|
5008
|
+
var toggleBtn = function ($btn, isEnable) {
|
5009
|
+
$btn.toggleClass('disabled', !isEnable);
|
5010
|
+
$btn.attr('disabled', !isEnable);
|
5011
|
+
};
|
5012
|
+
|
5013
|
+
/**
|
5014
|
+
* bind enter key
|
5015
|
+
*
|
5016
|
+
* @private
|
5017
|
+
* @param {jQuery} $input
|
5018
|
+
* @param {jQuery} $btn
|
5019
|
+
*/
|
5020
|
+
var bindEnterKey = function ($input, $btn) {
|
5021
|
+
$input.on('keypress', function (event) {
|
5022
|
+
if (event.keyCode === key.code.ENTER) {
|
5023
|
+
$btn.trigger('click');
|
5024
|
+
}
|
5025
|
+
});
|
5026
|
+
};
|
5027
|
+
|
5028
|
+
this.show = function (layoutInfo) {
|
5029
|
+
var $dialog = layoutInfo.dialog(),
|
5030
|
+
$editable = layoutInfo.editable();
|
5031
|
+
|
5032
|
+
handler.invoke('editor.saveRange', $editable);
|
5033
|
+
this.showImageDialog($editable, $dialog).then(function (data) {
|
5034
|
+
handler.invoke('editor.restoreRange', $editable);
|
5035
|
+
|
5036
|
+
if (typeof data === 'string') {
|
5037
|
+
// image url
|
5038
|
+
handler.invoke('editor.insertImage', $editable, data);
|
5039
|
+
} else {
|
5040
|
+
// array of files
|
5041
|
+
handler.insertImages(layoutInfo, data);
|
5042
|
+
}
|
5043
|
+
}).fail(function () {
|
5044
|
+
handler.invoke('editor.restoreRange', $editable);
|
5045
|
+
});
|
5046
|
+
};
|
5047
|
+
|
5048
|
+
/**
|
5049
|
+
* show image dialog
|
5050
|
+
*
|
5051
|
+
* @param {jQuery} $editable
|
5052
|
+
* @param {jQuery} $dialog
|
5053
|
+
* @return {Promise}
|
5054
|
+
*/
|
5055
|
+
this.showImageDialog = function ($editable, $dialog) {
|
5056
|
+
return $.Deferred(function (deferred) {
|
5057
|
+
var $imageDialog = $dialog.find('.note-image-dialog');
|
5058
|
+
|
5059
|
+
var $imageInput = $dialog.find('.note-image-input'),
|
5060
|
+
$imageUrl = $dialog.find('.note-image-url'),
|
5061
|
+
$imageBtn = $dialog.find('.note-image-btn');
|
5062
|
+
|
5063
|
+
$imageDialog.one('shown.bs.modal', function () {
|
5064
|
+
// Cloning imageInput to clear element.
|
5065
|
+
$imageInput.replaceWith($imageInput.clone()
|
5066
|
+
.on('change', function () {
|
5067
|
+
deferred.resolve(this.files || this.value);
|
5068
|
+
$imageDialog.modal('hide');
|
5069
|
+
})
|
5070
|
+
.val('')
|
5071
|
+
);
|
5072
|
+
|
5073
|
+
$imageBtn.click(function (event) {
|
5074
|
+
event.preventDefault();
|
5075
|
+
|
5076
|
+
deferred.resolve($imageUrl.val());
|
5077
|
+
$imageDialog.modal('hide');
|
5078
|
+
});
|
5079
|
+
|
5080
|
+
$imageUrl.on('keyup paste', function (event) {
|
5081
|
+
var url;
|
5082
|
+
|
5083
|
+
if (event.type === 'paste') {
|
5084
|
+
url = event.originalEvent.clipboardData.getData('text');
|
5085
|
+
} else {
|
5086
|
+
url = $imageUrl.val();
|
5087
|
+
}
|
5088
|
+
|
5089
|
+
toggleBtn($imageBtn, url);
|
5090
|
+
}).val('').trigger('focus');
|
5091
|
+
bindEnterKey($imageUrl, $imageBtn);
|
5092
|
+
}).one('hidden.bs.modal', function () {
|
5093
|
+
$imageInput.off('change');
|
5094
|
+
$imageUrl.off('keyup paste keypress');
|
5095
|
+
$imageBtn.off('click');
|
5096
|
+
|
5097
|
+
if (deferred.state() === 'pending') {
|
5098
|
+
deferred.reject();
|
5099
|
+
}
|
5100
|
+
}).modal('show');
|
5101
|
+
});
|
5102
|
+
};
|
5103
|
+
};
|
5104
|
+
|
5105
|
+
var HelpDialog = function (handler) {
|
4342
5106
|
/**
|
4343
5107
|
* show help dialog
|
4344
5108
|
*
|
@@ -4355,62 +5119,89 @@
|
|
4355
5119
|
}).modal('show');
|
4356
5120
|
}).promise();
|
4357
5121
|
};
|
4358
|
-
};
|
4359
5122
|
|
5123
|
+
/**
|
5124
|
+
* @param {Object} layoutInfo
|
5125
|
+
*/
|
5126
|
+
this.show = function (layoutInfo) {
|
5127
|
+
var $dialog = layoutInfo.dialog(),
|
5128
|
+
$editable = layoutInfo.editable();
|
4360
5129
|
|
4361
|
-
|
4362
|
-
|
4363
|
-
|
4364
|
-
require(['CodeMirror'], function (cm) {
|
4365
|
-
CodeMirror = cm;
|
5130
|
+
handler.invoke('editor.saveRange', $editable, true);
|
5131
|
+
this.showHelpDialog($editable, $dialog).then(function () {
|
5132
|
+
handler.invoke('editor.restoreRange', $editable);
|
4366
5133
|
});
|
4367
|
-
}
|
4368
|
-
|
4369
|
-
|
4370
|
-
}
|
5134
|
+
};
|
5135
|
+
};
|
5136
|
+
|
4371
5137
|
|
4372
5138
|
/**
|
4373
5139
|
* @class EventHandler
|
4374
5140
|
*
|
4375
5141
|
* EventHandler
|
5142
|
+
* - TODO: new instance per a editor
|
5143
|
+
* - TODO: rename EventHandler
|
4376
5144
|
*/
|
4377
5145
|
var EventHandler = function () {
|
4378
|
-
var $window = $(window);
|
4379
|
-
var $document = $(document);
|
4380
|
-
var $scrollbar = $('html, body');
|
4381
|
-
|
4382
|
-
var editor = new Editor();
|
4383
|
-
var toolbar = new Toolbar(), popover = new Popover();
|
4384
|
-
var handle = new Handle(), dialog = new Dialog();
|
4385
|
-
|
4386
5146
|
/**
|
4387
|
-
*
|
4388
|
-
* @returns {editing.Editor}
|
5147
|
+
* Modules
|
4389
5148
|
*/
|
4390
|
-
this.
|
4391
|
-
|
5149
|
+
var modules = this.modules = {
|
5150
|
+
editor: new Editor(this),
|
5151
|
+
toolbar: new Toolbar(this),
|
5152
|
+
statusbar: new Statusbar(this),
|
5153
|
+
popover: new Popover(this),
|
5154
|
+
handle: new Handle(this),
|
5155
|
+
fullscreen: new Fullscreen(this),
|
5156
|
+
codeview: new Codeview(this),
|
5157
|
+
dragAndDrop: new DragAndDrop(this),
|
5158
|
+
clipboard: new Clipboard(this),
|
5159
|
+
linkDialog: new LinkDialog(this),
|
5160
|
+
imageDialog: new ImageDialog(this),
|
5161
|
+
helpDialog: new HelpDialog(this)
|
5162
|
+
};
|
5163
|
+
|
5164
|
+
// TODO refactor modules and eventHandler
|
5165
|
+
// - remove this method and use custom event from $holder instead
|
5166
|
+
this.invoke = function () {
|
5167
|
+
var moduleAndMethod = list.head(list.from(arguments));
|
5168
|
+
var args = list.tail(list.from(arguments));
|
5169
|
+
|
5170
|
+
var splits = moduleAndMethod.split('.');
|
5171
|
+
var hasSeparator = splits.length > 1;
|
5172
|
+
var moduleName = hasSeparator && list.head(splits);
|
5173
|
+
var methodName = hasSeparator ? list.last(splits) : list.head(splits);
|
5174
|
+
|
5175
|
+
var module = this.getModule(moduleName);
|
5176
|
+
var method = module[methodName];
|
5177
|
+
|
5178
|
+
return method && method.apply(module, args);
|
4392
5179
|
};
|
4393
5180
|
|
4394
5181
|
/**
|
4395
|
-
* returns
|
5182
|
+
* returns module
|
4396
5183
|
*
|
4397
|
-
* @
|
4398
|
-
* @
|
4399
|
-
* @return {Object}
|
5184
|
+
* @param {String} moduleName - name of module
|
5185
|
+
* @return {Module} - defaults is editor
|
4400
5186
|
*/
|
4401
|
-
|
4402
|
-
|
4403
|
-
|
4404
|
-
if (!$target.length) { return null; }
|
4405
|
-
|
4406
|
-
var $editor;
|
4407
|
-
if ($target.is('.note-editor, .note-air-editor')) {
|
4408
|
-
$editor = $target;
|
4409
|
-
} else {
|
4410
|
-
$editor = $('#note-editor-' + list.last($target.attr('id').split('-')));
|
4411
|
-
}
|
5187
|
+
this.getModule = function (moduleName) {
|
5188
|
+
return this.modules[moduleName] || this.modules.editor;
|
5189
|
+
};
|
4412
5190
|
|
4413
|
-
|
5191
|
+
/**
|
5192
|
+
* @param {jQuery} $holder
|
5193
|
+
* @param {Object} callbacks
|
5194
|
+
* @param {String} eventNamespace
|
5195
|
+
* @returns {Function}
|
5196
|
+
*/
|
5197
|
+
var bindCustomEvent = this.bindCustomEvent = function ($holder, callbacks, eventNamespace) {
|
5198
|
+
return function () {
|
5199
|
+
var callback = callbacks[func.namespaceToCamel(eventNamespace, 'on')];
|
5200
|
+
if (callback) {
|
5201
|
+
callback(arguments);
|
5202
|
+
}
|
5203
|
+
return $holder.trigger('summernote.' + eventNamespace, arguments);
|
5204
|
+
};
|
4414
5205
|
};
|
4415
5206
|
|
4416
5207
|
/**
|
@@ -4420,33 +5211,28 @@
|
|
4420
5211
|
* @param {Object} layoutInfo
|
4421
5212
|
* @param {File[]} files
|
4422
5213
|
*/
|
4423
|
-
|
5214
|
+
this.insertImages = function (layoutInfo, files) {
|
4424
5215
|
var $editor = layoutInfo.editor(),
|
4425
|
-
$editable = layoutInfo.editable()
|
5216
|
+
$editable = layoutInfo.editable(),
|
5217
|
+
$holder = layoutInfo.holder();
|
4426
5218
|
|
4427
5219
|
var callbacks = $editable.data('callbacks');
|
4428
5220
|
var options = $editor.data('options');
|
4429
5221
|
|
4430
5222
|
// If onImageUpload options setted
|
4431
5223
|
if (callbacks.onImageUpload) {
|
4432
|
-
|
5224
|
+
bindCustomEvent($holder, callbacks, 'image.upload')([files]);
|
4433
5225
|
// else insert Image as dataURL
|
4434
5226
|
} else {
|
4435
5227
|
$.each(files, function (idx, file) {
|
4436
5228
|
var filename = file.name;
|
4437
5229
|
if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {
|
4438
|
-
|
4439
|
-
callbacks.onImageUploadError(options.langInfo.image.maximumFileSizeError);
|
4440
|
-
} else {
|
4441
|
-
alert(options.langInfo.image.maximumFileSizeError);
|
4442
|
-
}
|
5230
|
+
bindCustomEvent($holder, callbacks, 'image.upload.error')(options.langInfo.image.maximumFileSizeError);
|
4443
5231
|
} else {
|
4444
5232
|
async.readFileAsDataURL(file).then(function (sDataURL) {
|
4445
|
-
editor.insertImage($editable, sDataURL, filename);
|
5233
|
+
modules.editor.insertImage($editable, sDataURL, filename);
|
4446
5234
|
}).fail(function () {
|
4447
|
-
|
4448
|
-
callbacks.onImageUploadError();
|
4449
|
-
}
|
5235
|
+
bindCustomEvent($holder, callbacks, 'image.upload.error')(options.langInfo.image.maximumFileSizeError);
|
4450
5236
|
});
|
4451
5237
|
}
|
4452
5238
|
});
|
@@ -4458,303 +5244,67 @@
|
|
4458
5244
|
* @param {Object} layoutInfo
|
4459
5245
|
*/
|
4460
5246
|
showLinkDialog: function (layoutInfo) {
|
4461
|
-
|
4462
|
-
$dialog = layoutInfo.dialog(),
|
4463
|
-
$editable = layoutInfo.editable(),
|
4464
|
-
linkInfo = editor.getLinkInfo($editable);
|
4465
|
-
|
4466
|
-
var options = $editor.data('options');
|
4467
|
-
|
4468
|
-
editor.saveRange($editable);
|
4469
|
-
dialog.showLinkDialog($editable, $dialog, linkInfo).then(function (linkInfo) {
|
4470
|
-
editor.restoreRange($editable);
|
4471
|
-
editor.createLink($editable, linkInfo, options);
|
4472
|
-
// hide popover after creating link
|
4473
|
-
popover.hide(layoutInfo.popover());
|
4474
|
-
}).fail(function () {
|
4475
|
-
editor.restoreRange($editable);
|
4476
|
-
});
|
5247
|
+
modules.linkDialog.show(layoutInfo);
|
4477
5248
|
},
|
4478
5249
|
|
4479
5250
|
/**
|
4480
5251
|
* @param {Object} layoutInfo
|
4481
5252
|
*/
|
4482
5253
|
showImageDialog: function (layoutInfo) {
|
4483
|
-
|
4484
|
-
$editable = layoutInfo.editable();
|
4485
|
-
|
4486
|
-
editor.saveRange($editable);
|
4487
|
-
dialog.showImageDialog($editable, $dialog).then(function (data) {
|
4488
|
-
editor.restoreRange($editable);
|
4489
|
-
|
4490
|
-
if (typeof data === 'string') {
|
4491
|
-
// image url
|
4492
|
-
editor.insertImage($editable, data);
|
4493
|
-
} else {
|
4494
|
-
// array of files
|
4495
|
-
insertImages(layoutInfo, data);
|
4496
|
-
}
|
4497
|
-
}).fail(function () {
|
4498
|
-
editor.restoreRange($editable);
|
4499
|
-
});
|
5254
|
+
modules.imageDialog.show(layoutInfo);
|
4500
5255
|
},
|
4501
5256
|
|
4502
5257
|
/**
|
4503
5258
|
* @param {Object} layoutInfo
|
4504
5259
|
*/
|
4505
5260
|
showHelpDialog: function (layoutInfo) {
|
4506
|
-
|
4507
|
-
$editable = layoutInfo.editable();
|
4508
|
-
|
4509
|
-
editor.saveRange($editable, true);
|
4510
|
-
dialog.showHelpDialog($editable, $dialog).then(function () {
|
4511
|
-
editor.restoreRange($editable);
|
4512
|
-
});
|
4513
|
-
},
|
4514
|
-
|
4515
|
-
fullscreen: function (layoutInfo) {
|
4516
|
-
var $editor = layoutInfo.editor(),
|
4517
|
-
$toolbar = layoutInfo.toolbar(),
|
4518
|
-
$editable = layoutInfo.editable(),
|
4519
|
-
$codable = layoutInfo.codable();
|
4520
|
-
|
4521
|
-
var resize = function (size) {
|
4522
|
-
$editable.css('height', size.h);
|
4523
|
-
$codable.css('height', size.h);
|
4524
|
-
if ($codable.data('cmeditor')) {
|
4525
|
-
$codable.data('cmeditor').setsize(null, size.h);
|
4526
|
-
}
|
4527
|
-
};
|
4528
|
-
|
4529
|
-
$editor.toggleClass('fullscreen');
|
4530
|
-
var isFullscreen = $editor.hasClass('fullscreen');
|
4531
|
-
if (isFullscreen) {
|
4532
|
-
$editable.data('orgheight', $editable.css('height'));
|
4533
|
-
|
4534
|
-
$window.on('resize', function () {
|
4535
|
-
resize({
|
4536
|
-
h: $window.height() - $toolbar.outerHeight()
|
4537
|
-
});
|
4538
|
-
}).trigger('resize');
|
4539
|
-
|
4540
|
-
$scrollbar.css('overflow', 'hidden');
|
4541
|
-
} else {
|
4542
|
-
$window.off('resize');
|
4543
|
-
resize({
|
4544
|
-
h: $editable.data('orgheight')
|
4545
|
-
});
|
4546
|
-
$scrollbar.css('overflow', 'visible');
|
4547
|
-
}
|
4548
|
-
|
4549
|
-
toolbar.updateFullscreen($toolbar, isFullscreen);
|
5261
|
+
modules.helpDialog.show(layoutInfo);
|
4550
5262
|
},
|
4551
5263
|
|
4552
|
-
|
4553
|
-
|
4554
|
-
|
4555
|
-
|
4556
|
-
|
4557
|
-
|
4558
|
-
$handle = layoutInfo.handle();
|
4559
|
-
|
4560
|
-
var options = $editor.data('options');
|
4561
|
-
|
4562
|
-
var cmEditor, server;
|
4563
|
-
|
4564
|
-
$editor.toggleClass('codeview');
|
4565
|
-
|
4566
|
-
var isCodeview = $editor.hasClass('codeview');
|
4567
|
-
if (isCodeview) {
|
4568
|
-
$codable.val(dom.html($editable, options.prettifyHtml));
|
4569
|
-
$codable.height($editable.height());
|
4570
|
-
toolbar.deactivate($toolbar);
|
4571
|
-
popover.hide($popover);
|
4572
|
-
handle.hide($handle);
|
4573
|
-
$codable.focus();
|
4574
|
-
|
4575
|
-
// activate CodeMirror as codable
|
4576
|
-
if (agent.hasCodeMirror) {
|
4577
|
-
cmEditor = CodeMirror.fromTextArea($codable[0], options.codemirror);
|
4578
|
-
|
4579
|
-
// CodeMirror TernServer
|
4580
|
-
if (options.codemirror.tern) {
|
4581
|
-
server = new CodeMirror.TernServer(options.codemirror.tern);
|
4582
|
-
cmEditor.ternServer = server;
|
4583
|
-
cmEditor.on('cursorActivity', function (cm) {
|
4584
|
-
server.updateArgHints(cm);
|
4585
|
-
});
|
4586
|
-
}
|
4587
|
-
|
4588
|
-
// CodeMirror hasn't Padding.
|
4589
|
-
cmEditor.setSize(null, $editable.outerHeight());
|
4590
|
-
$codable.data('cmEditor', cmEditor);
|
4591
|
-
}
|
4592
|
-
} else {
|
4593
|
-
// deactivate CodeMirror as codable
|
4594
|
-
if (agent.hasCodeMirror) {
|
4595
|
-
cmEditor = $codable.data('cmEditor');
|
4596
|
-
$codable.val(cmEditor.getValue());
|
4597
|
-
cmEditor.toTextArea();
|
4598
|
-
}
|
4599
|
-
|
4600
|
-
$editable.html(dom.value($codable, options.prettifyHtml) || dom.emptyPara);
|
4601
|
-
$editable.height(options.height ? $codable.height() : 'auto');
|
4602
|
-
|
4603
|
-
toolbar.activate($toolbar);
|
4604
|
-
$editable.focus();
|
4605
|
-
}
|
4606
|
-
|
4607
|
-
toolbar.updateCodeview(layoutInfo.toolbar(), isCodeview);
|
4608
|
-
}
|
4609
|
-
};
|
4610
|
-
|
4611
|
-
var hMousedown = function (event) {
|
4612
|
-
//preventDefault Selection for FF, IE8+
|
4613
|
-
if (dom.isImg(event.target)) {
|
4614
|
-
event.preventDefault();
|
4615
|
-
}
|
4616
|
-
};
|
4617
|
-
|
4618
|
-
var hToolbarAndPopoverUpdate = function (event) {
|
4619
|
-
// delay for range after mouseup
|
4620
|
-
setTimeout(function () {
|
4621
|
-
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
|
4622
|
-
var styleInfo = editor.currentStyle(event.target);
|
4623
|
-
if (!styleInfo) { return; }
|
4624
|
-
|
4625
|
-
var isAirMode = layoutInfo.editor().data('options').airMode;
|
4626
|
-
if (!isAirMode) {
|
4627
|
-
toolbar.update(layoutInfo.toolbar(), styleInfo);
|
4628
|
-
}
|
4629
|
-
|
4630
|
-
popover.update(layoutInfo.popover(), styleInfo, isAirMode);
|
4631
|
-
handle.update(layoutInfo.handle(), styleInfo, isAirMode);
|
4632
|
-
}, 0);
|
4633
|
-
};
|
4634
|
-
|
4635
|
-
var hScroll = function (event) {
|
4636
|
-
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
|
4637
|
-
//hide popover and handle when scrolled
|
4638
|
-
popover.hide(layoutInfo.popover());
|
4639
|
-
handle.hide(layoutInfo.handle());
|
4640
|
-
};
|
4641
|
-
|
4642
|
-
/**
|
4643
|
-
* paste clipboard image
|
4644
|
-
*
|
4645
|
-
* @param {Event} event
|
4646
|
-
*/
|
4647
|
-
var hPasteClipboardImage = function (event) {
|
4648
|
-
var clipboardData = event.originalEvent.clipboardData;
|
4649
|
-
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
|
4650
|
-
var $editable = layoutInfo.editable();
|
4651
|
-
|
4652
|
-
if (!clipboardData || !clipboardData.items || !clipboardData.items.length) {
|
4653
|
-
var callbacks = $editable.data('callbacks');
|
4654
|
-
// only can run if it has onImageUpload method
|
4655
|
-
if (!callbacks.onImageUpload) {
|
4656
|
-
return;
|
4657
|
-
}
|
4658
|
-
|
4659
|
-
// save cursor
|
4660
|
-
editor.saveNode($editable);
|
4661
|
-
editor.saveRange($editable);
|
4662
|
-
|
4663
|
-
$editable.html('');
|
4664
|
-
|
4665
|
-
setTimeout(function () {
|
4666
|
-
var $img = $editable.find('img');
|
4667
|
-
|
4668
|
-
if (!$img.length || $img[0].src.indexOf('data:') === -1) {
|
4669
|
-
// pasted content
|
4670
|
-
var html = $editable.html();
|
4671
|
-
|
4672
|
-
editor.restoreNode($editable);
|
4673
|
-
editor.restoreRange($editable);
|
4674
|
-
|
4675
|
-
try {
|
4676
|
-
// insert normal dom code
|
4677
|
-
$(html).each(function () {
|
4678
|
-
$editable.focus();
|
4679
|
-
editor.insertNode($editable, this);
|
4680
|
-
});
|
4681
|
-
} catch (ex) {
|
4682
|
-
// insert text
|
4683
|
-
$editable.focus();
|
4684
|
-
editor.insertText($editable, html);
|
4685
|
-
}
|
4686
|
-
return;
|
4687
|
-
}
|
4688
|
-
|
4689
|
-
var datauri = $img[0].src;
|
4690
|
-
var data = atob(datauri.split(',')[1]);
|
4691
|
-
var array = new Uint8Array(data.length);
|
4692
|
-
for (var i = 0; i < data.length; i++) {
|
4693
|
-
array[i] = data.charCodeAt(i);
|
4694
|
-
}
|
4695
|
-
|
4696
|
-
var blob = new Blob([array], { type : 'image/png'});
|
4697
|
-
blob.name = 'clipboard.png';
|
4698
|
-
|
4699
|
-
editor.restoreNode($editable);
|
4700
|
-
editor.restoreRange($editable);
|
4701
|
-
insertImages(layoutInfo, [blob]);
|
4702
|
-
|
4703
|
-
editor.afterCommand($editable);
|
4704
|
-
}, 0);
|
4705
|
-
|
4706
|
-
return;
|
4707
|
-
}
|
4708
|
-
|
4709
|
-
var item = list.head(clipboardData.items);
|
4710
|
-
var isClipboardImage = item.kind === 'file' && item.type.indexOf('image/') !== -1;
|
4711
|
-
|
4712
|
-
if (isClipboardImage) {
|
4713
|
-
insertImages(layoutInfo, [item.getAsFile()]);
|
4714
|
-
}
|
4715
|
-
|
4716
|
-
editor.afterCommand($editable);
|
4717
|
-
};
|
4718
|
-
|
4719
|
-
/**
|
4720
|
-
* `mousedown` event handler on $handle
|
4721
|
-
* - controlSizing: resize image
|
4722
|
-
*
|
4723
|
-
* @param {MouseEvent} event
|
4724
|
-
*/
|
4725
|
-
var hHandleMousedown = function (event) {
|
4726
|
-
if (dom.isControlSizing(event.target)) {
|
4727
|
-
event.preventDefault();
|
4728
|
-
event.stopPropagation();
|
5264
|
+
/**
|
5265
|
+
* @param {Object} layoutInfo
|
5266
|
+
*/
|
5267
|
+
fullscreen: function (layoutInfo) {
|
5268
|
+
modules.fullscreen.toggle(layoutInfo);
|
5269
|
+
},
|
4729
5270
|
|
4730
|
-
|
4731
|
-
|
4732
|
-
|
4733
|
-
|
5271
|
+
/**
|
5272
|
+
* @param {Object} layoutInfo
|
5273
|
+
*/
|
5274
|
+
codeview: function (layoutInfo) {
|
5275
|
+
modules.codeview.toggle(layoutInfo);
|
5276
|
+
}
|
5277
|
+
};
|
4734
5278
|
|
4735
|
-
|
4736
|
-
|
4737
|
-
|
5279
|
+
var hMousedown = function (event) {
|
5280
|
+
//preventDefault Selection for FF, IE8+
|
5281
|
+
if (dom.isImg(event.target)) {
|
5282
|
+
event.preventDefault();
|
5283
|
+
}
|
5284
|
+
};
|
4738
5285
|
|
4739
|
-
|
5286
|
+
var hToolbarAndPopoverUpdate = function (event) {
|
5287
|
+
// delay for range after mouseup
|
5288
|
+
setTimeout(function () {
|
5289
|
+
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
|
5290
|
+
var styleInfo = modules.editor.currentStyle(event.target);
|
5291
|
+
if (!styleInfo) { return; }
|
4740
5292
|
|
4741
|
-
|
4742
|
-
|
4743
|
-
|
4744
|
-
|
4745
|
-
}, $target, !event.shiftKey);
|
5293
|
+
var isAirMode = layoutInfo.editor().data('options').airMode;
|
5294
|
+
if (!isAirMode) {
|
5295
|
+
modules.toolbar.update(layoutInfo.toolbar(), styleInfo);
|
5296
|
+
}
|
4746
5297
|
|
4747
|
-
|
4748
|
-
|
4749
|
-
|
4750
|
-
|
4751
|
-
editor.afterCommand($editable);
|
4752
|
-
});
|
5298
|
+
modules.popover.update(layoutInfo.popover(), styleInfo, isAirMode);
|
5299
|
+
modules.handle.update(layoutInfo.handle(), styleInfo, isAirMode);
|
5300
|
+
}, 0);
|
5301
|
+
};
|
4753
5302
|
|
4754
|
-
|
4755
|
-
|
4756
|
-
|
4757
|
-
|
5303
|
+
var hScroll = function (event) {
|
5304
|
+
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
|
5305
|
+
//hide popover and handle when scrolled
|
5306
|
+
modules.popover.hide(layoutInfo.popover());
|
5307
|
+
modules.handle.hide(layoutInfo.handle());
|
4758
5308
|
};
|
4759
5309
|
|
4760
5310
|
var hToolbarAndPopoverMousedown = function (event) {
|
@@ -4773,7 +5323,7 @@
|
|
4773
5323
|
value = $btn.attr('data-value'),
|
4774
5324
|
hide = $btn.attr('data-hide');
|
4775
5325
|
|
4776
|
-
var layoutInfo = makeLayoutInfo(event.target);
|
5326
|
+
var layoutInfo = dom.makeLayoutInfo(event.target);
|
4777
5327
|
|
4778
5328
|
// before command: detect control selection element($target)
|
4779
5329
|
var $target;
|
@@ -4789,11 +5339,11 @@
|
|
4789
5339
|
}
|
4790
5340
|
|
4791
5341
|
if ($.isFunction($.summernote.pluginEvents[eventName])) {
|
4792
|
-
$.summernote.pluginEvents[eventName](event, editor, layoutInfo, value);
|
4793
|
-
} else if (editor[eventName]) { // on command
|
5342
|
+
$.summernote.pluginEvents[eventName](event, modules.editor, layoutInfo, value);
|
5343
|
+
} else if (modules.editor[eventName]) { // on command
|
4794
5344
|
var $editable = layoutInfo.editable();
|
4795
|
-
$editable.
|
4796
|
-
editor[eventName]($editable, value, $target);
|
5345
|
+
$editable.focus();
|
5346
|
+
modules.editor[eventName]($editable, value, $target);
|
4797
5347
|
event.preventDefault();
|
4798
5348
|
} else if (commands[eventName]) {
|
4799
5349
|
commands[eventName].call(this, layoutInfo);
|
@@ -4803,7 +5353,7 @@
|
|
4803
5353
|
// after command
|
4804
5354
|
if ($.inArray(eventName, ['backColor', 'foreColor']) !== -1) {
|
4805
5355
|
var options = layoutInfo.editor().data('options', options);
|
4806
|
-
var module = options.airMode ? popover : toolbar;
|
5356
|
+
var module = options.airMode ? modules.popover : modules.toolbar;
|
4807
5357
|
module.updateRecentColor(list.head($btn), eventName, value);
|
4808
5358
|
}
|
4809
5359
|
|
@@ -4811,34 +5361,6 @@
|
|
4811
5361
|
}
|
4812
5362
|
};
|
4813
5363
|
|
4814
|
-
var EDITABLE_PADDING = 24;
|
4815
|
-
/**
|
4816
|
-
* `mousedown` event handler on statusbar
|
4817
|
-
*
|
4818
|
-
* @param {MouseEvent} event
|
4819
|
-
*/
|
4820
|
-
var hStatusbarMousedown = function (event) {
|
4821
|
-
event.preventDefault();
|
4822
|
-
event.stopPropagation();
|
4823
|
-
|
4824
|
-
var $editable = makeLayoutInfo(event.target).editable();
|
4825
|
-
var nEditableTop = $editable.offset().top - $document.scrollTop();
|
4826
|
-
|
4827
|
-
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
|
4828
|
-
var options = layoutInfo.editor().data('options');
|
4829
|
-
|
4830
|
-
$document.on('mousemove', function (event) {
|
4831
|
-
var nHeight = event.clientY - (nEditableTop + EDITABLE_PADDING);
|
4832
|
-
|
4833
|
-
nHeight = (options.minHeight > 0) ? Math.max(nHeight, options.minHeight) : nHeight;
|
4834
|
-
nHeight = (options.maxHeight > 0) ? Math.min(nHeight, options.maxHeight) : nHeight;
|
4835
|
-
|
4836
|
-
$editable.height(nHeight);
|
4837
|
-
}).one('mouseup', function () {
|
4838
|
-
$document.off('mousemove');
|
4839
|
-
});
|
4840
|
-
};
|
4841
|
-
|
4842
5364
|
var PX_PER_EM = 18;
|
4843
5365
|
var hDimensionPickerMove = function (event, options) {
|
4844
5366
|
var $picker = $(event.target.parentNode); // target is mousecatcher
|
@@ -4880,95 +5402,7 @@
|
|
4880
5402
|
|
4881
5403
|
$dimensionDisplay.html(dim.c + ' x ' + dim.r);
|
4882
5404
|
};
|
4883
|
-
|
4884
|
-
/**
|
4885
|
-
* Drag and Drop Events
|
4886
|
-
*
|
4887
|
-
* @param {Object} layoutInfo - layout Informations
|
4888
|
-
* @param {Object} options
|
4889
|
-
*/
|
4890
|
-
var handleDragAndDropEvent = function (layoutInfo, options) {
|
4891
|
-
if (options.disableDragAndDrop) {
|
4892
|
-
// prevent default drop event
|
4893
|
-
$document.on('drop', function (e) {
|
4894
|
-
e.preventDefault();
|
4895
|
-
});
|
4896
|
-
} else {
|
4897
|
-
attachDragAndDropEvent(layoutInfo, options);
|
4898
|
-
}
|
4899
|
-
};
|
4900
|
-
|
4901
|
-
/**
|
4902
|
-
* attach Drag and Drop Events
|
4903
|
-
*
|
4904
|
-
* @param {Object} layoutInfo - layout Informations
|
4905
|
-
* @param {Object} options
|
4906
|
-
*/
|
4907
|
-
var attachDragAndDropEvent = function (layoutInfo, options) {
|
4908
|
-
var collection = $(),
|
4909
|
-
$dropzone = layoutInfo.dropzone,
|
4910
|
-
$dropzoneMessage = layoutInfo.dropzone.find('.note-dropzone-message');
|
4911
|
-
|
4912
|
-
// show dropzone on dragenter when dragging a object to document.
|
4913
|
-
$document.on('dragenter', function (e) {
|
4914
|
-
var isCodeview = layoutInfo.editor.hasClass('codeview');
|
4915
|
-
if (!isCodeview && !collection.length) {
|
4916
|
-
layoutInfo.editor.addClass('dragover');
|
4917
|
-
$dropzone.width(layoutInfo.editor.width());
|
4918
|
-
$dropzone.height(layoutInfo.editor.height());
|
4919
|
-
$dropzoneMessage.text(options.langInfo.image.dragImageHere);
|
4920
|
-
}
|
4921
|
-
collection = collection.add(e.target);
|
4922
|
-
}).on('dragleave', function (e) {
|
4923
|
-
collection = collection.not(e.target);
|
4924
|
-
if (!collection.length) {
|
4925
|
-
layoutInfo.editor.removeClass('dragover');
|
4926
|
-
}
|
4927
|
-
}).on('drop', function () {
|
4928
|
-
collection = $();
|
4929
|
-
layoutInfo.editor.removeClass('dragover');
|
4930
|
-
}).on('mouseout', function (e) {
|
4931
|
-
collection = collection.not(e.target);
|
4932
|
-
if (!collection.length) {
|
4933
|
-
layoutInfo.editor.removeClass('dragover');
|
4934
|
-
}
|
4935
|
-
});
|
4936
|
-
|
4937
|
-
// change dropzone's message on hover.
|
4938
|
-
$dropzone.on('dragenter', function () {
|
4939
|
-
$dropzone.addClass('hover');
|
4940
|
-
$dropzoneMessage.text(options.langInfo.image.dropImage);
|
4941
|
-
}).on('dragleave', function () {
|
4942
|
-
$dropzone.removeClass('hover');
|
4943
|
-
$dropzoneMessage.text(options.langInfo.image.dragImageHere);
|
4944
|
-
});
|
4945
|
-
|
4946
|
-
// attach dropImage
|
4947
|
-
$dropzone.on('drop', function (event) {
|
4948
|
-
event.preventDefault();
|
4949
|
-
|
4950
|
-
var dataTransfer = event.originalEvent.dataTransfer;
|
4951
|
-
var html = dataTransfer.getData('text/html');
|
4952
|
-
var text = dataTransfer.getData('text/plain');
|
4953
|
-
|
4954
|
-
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
|
4955
|
-
|
4956
|
-
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
|
4957
|
-
layoutInfo.editable().focus();
|
4958
|
-
insertImages(layoutInfo, dataTransfer.files);
|
4959
|
-
} else if (html) {
|
4960
|
-
$(html).each(function () {
|
4961
|
-
layoutInfo.editable().focus();
|
4962
|
-
editor.insertNode(layoutInfo.editable(), this);
|
4963
|
-
});
|
4964
|
-
} else if (text) {
|
4965
|
-
layoutInfo.editable().focus();
|
4966
|
-
editor.insertText(layoutInfo.editable(), text);
|
4967
|
-
}
|
4968
|
-
}).on('dragover', false); // prevent default dragover event
|
4969
|
-
};
|
4970
|
-
|
4971
|
-
|
5405
|
+
|
4972
5406
|
/**
|
4973
5407
|
* bind KeyMap on keydown
|
4974
5408
|
*
|
@@ -4976,39 +5410,39 @@
|
|
4976
5410
|
* @param {Object} keyMap
|
4977
5411
|
*/
|
4978
5412
|
this.bindKeyMap = function (layoutInfo, keyMap) {
|
4979
|
-
var $editor = layoutInfo.editor;
|
4980
|
-
var $editable = layoutInfo.editable;
|
4981
|
-
|
4982
|
-
layoutInfo = makeLayoutInfo($editable);
|
5413
|
+
var $editor = layoutInfo.editor();
|
5414
|
+
var $editable = layoutInfo.editable();
|
4983
5415
|
|
4984
5416
|
$editable.on('keydown', function (event) {
|
4985
|
-
var
|
5417
|
+
var keys = [];
|
4986
5418
|
|
4987
5419
|
// modifier
|
4988
|
-
if (event.metaKey) {
|
4989
|
-
if (event.ctrlKey && !event.altKey) {
|
4990
|
-
if (event.shiftKey) {
|
5420
|
+
if (event.metaKey) { keys.push('CMD'); }
|
5421
|
+
if (event.ctrlKey && !event.altKey) { keys.push('CTRL'); }
|
5422
|
+
if (event.shiftKey) { keys.push('SHIFT'); }
|
4991
5423
|
|
4992
5424
|
// keycode
|
4993
5425
|
var keyName = key.nameFromCode[event.keyCode];
|
4994
|
-
if (keyName) {
|
5426
|
+
if (keyName) {
|
5427
|
+
keys.push(keyName);
|
5428
|
+
}
|
4995
5429
|
|
4996
|
-
var eventName = keyMap[
|
5430
|
+
var eventName = keyMap[keys.join('+')];
|
4997
5431
|
if (eventName) {
|
4998
5432
|
if ($.summernote.pluginEvents[eventName]) {
|
4999
5433
|
var plugin = $.summernote.pluginEvents[eventName];
|
5000
5434
|
if ($.isFunction(plugin)) {
|
5001
|
-
plugin(event, editor, layoutInfo);
|
5435
|
+
plugin(event, modules.editor, layoutInfo);
|
5002
5436
|
}
|
5003
|
-
} else if (editor[eventName]) {
|
5004
|
-
editor[eventName]($editable, $editor.data('options'));
|
5437
|
+
} else if (modules.editor[eventName]) {
|
5438
|
+
modules.editor[eventName]($editable, $editor.data('options'));
|
5005
5439
|
event.preventDefault();
|
5006
5440
|
} else if (commands[eventName]) {
|
5007
5441
|
commands[eventName].call(this, layoutInfo);
|
5008
5442
|
event.preventDefault();
|
5009
5443
|
}
|
5010
5444
|
} else if (key.isEdit(event.keyCode)) {
|
5011
|
-
editor.afterCommand($editable);
|
5445
|
+
modules.editor.afterCommand($editable);
|
5012
5446
|
}
|
5013
5447
|
});
|
5014
5448
|
};
|
@@ -5018,48 +5452,38 @@
|
|
5018
5452
|
*
|
5019
5453
|
* @param {Object} layoutInfo - layout Informations
|
5020
5454
|
* @param {Object} options - user options include custom event handlers
|
5021
|
-
* @param {function(event)} [options.onenter] - enter key handler
|
5022
|
-
* @param {function(event)} [options.onfocus]
|
5023
|
-
* @param {function(event)} [options.onblur]
|
5024
|
-
* @param {function(event)} [options.onkeyup]
|
5025
|
-
* @param {function(event)} [options.onkeydown]
|
5026
|
-
* @param {function(event)} [options.onpaste]
|
5027
|
-
* @param {function(event)} [options.onToolBarclick]
|
5028
|
-
* @param {function(event)} [options.onChange]
|
5029
5455
|
*/
|
5030
5456
|
this.attach = function (layoutInfo, options) {
|
5031
5457
|
// handlers for editable
|
5032
5458
|
if (options.shortcuts) {
|
5033
5459
|
this.bindKeyMap(layoutInfo, options.keyMap[agent.isMac ? 'mac' : 'pc']);
|
5034
5460
|
}
|
5035
|
-
layoutInfo.editable.on('mousedown', hMousedown);
|
5036
|
-
layoutInfo.editable.on('keyup mouseup', hToolbarAndPopoverUpdate);
|
5037
|
-
layoutInfo.editable.on('scroll', hScroll);
|
5038
|
-
|
5461
|
+
layoutInfo.editable().on('mousedown', hMousedown);
|
5462
|
+
layoutInfo.editable().on('keyup mouseup', hToolbarAndPopoverUpdate);
|
5463
|
+
layoutInfo.editable().on('scroll', hScroll);
|
5464
|
+
modules.clipboard.attach(layoutInfo, options);
|
5039
5465
|
|
5040
5466
|
// handler for handle and popover
|
5041
|
-
|
5042
|
-
layoutInfo.popover.on('click', hToolbarAndPopoverClick);
|
5043
|
-
layoutInfo.popover.on('mousedown', hToolbarAndPopoverMousedown);
|
5467
|
+
modules.handle.attach(layoutInfo, options);
|
5468
|
+
layoutInfo.popover().on('click', hToolbarAndPopoverClick);
|
5469
|
+
layoutInfo.popover().on('mousedown', hToolbarAndPopoverMousedown);
|
5470
|
+
|
5471
|
+
// handler for drag and drop
|
5472
|
+
modules.dragAndDrop.attach(layoutInfo, options);
|
5044
5473
|
|
5045
5474
|
// handlers for frame mode (toolbar, statusbar)
|
5046
5475
|
if (!options.airMode) {
|
5047
|
-
// handler for drag and drop
|
5048
|
-
handleDragAndDropEvent(layoutInfo, options);
|
5049
|
-
|
5050
5476
|
// handler for toolbar
|
5051
|
-
layoutInfo.toolbar.on('click', hToolbarAndPopoverClick);
|
5052
|
-
layoutInfo.toolbar.on('mousedown', hToolbarAndPopoverMousedown);
|
5477
|
+
layoutInfo.toolbar().on('click', hToolbarAndPopoverClick);
|
5478
|
+
layoutInfo.toolbar().on('mousedown', hToolbarAndPopoverMousedown);
|
5053
5479
|
|
5054
5480
|
// handler for statusbar
|
5055
|
-
|
5056
|
-
layoutInfo.statusbar.on('mousedown', hStatusbarMousedown);
|
5057
|
-
}
|
5481
|
+
modules.statusbar.attach(layoutInfo, options);
|
5058
5482
|
}
|
5059
5483
|
|
5060
5484
|
// handler for table dimension
|
5061
|
-
var $catcherContainer = options.airMode ? layoutInfo.popover :
|
5062
|
-
layoutInfo.toolbar;
|
5485
|
+
var $catcherContainer = options.airMode ? layoutInfo.popover() :
|
5486
|
+
layoutInfo.toolbar();
|
5063
5487
|
var $catcher = $catcherContainer.find('.note-dimension-picker-mousecatcher');
|
5064
5488
|
$catcher.css({
|
5065
5489
|
width: options.insertTableMaxSize.col + 'em',
|
@@ -5069,74 +5493,124 @@
|
|
5069
5493
|
});
|
5070
5494
|
|
5071
5495
|
// save options on editor
|
5072
|
-
layoutInfo.editor.data('options', options);
|
5496
|
+
layoutInfo.editor().data('options', options);
|
5073
5497
|
|
5074
5498
|
// ret styleWithCSS for backColor / foreColor clearing with 'inherit'.
|
5075
5499
|
if (!agent.isMSIE) {
|
5076
|
-
//
|
5500
|
+
// [workaround] for Firefox
|
5501
|
+
// - protect FF Error: NS_ERROR_FAILURE: Failure
|
5077
5502
|
setTimeout(function () {
|
5078
5503
|
document.execCommand('styleWithCSS', 0, options.styleWithSpan);
|
5079
5504
|
}, 0);
|
5080
5505
|
}
|
5081
5506
|
|
5082
5507
|
// History
|
5083
|
-
var history = new History(layoutInfo.editable);
|
5084
|
-
layoutInfo.editable.data('NoteHistory', history);
|
5085
|
-
|
5086
|
-
// basic event callbacks (lowercase)
|
5087
|
-
// enter, focus, blur, keyup, keydown
|
5088
|
-
if (options.onenter) {
|
5089
|
-
layoutInfo.editable.keypress(function (event) {
|
5090
|
-
if (event.keyCode === key.ENTER) { options.onenter(event); }
|
5091
|
-
});
|
5092
|
-
}
|
5093
|
-
|
5094
|
-
if (options.onfocus) { layoutInfo.editable.focus(options.onfocus); }
|
5095
|
-
if (options.onblur) { layoutInfo.editable.blur(options.onblur); }
|
5096
|
-
if (options.onkeyup) { layoutInfo.editable.keyup(options.onkeyup); }
|
5097
|
-
if (options.onkeydown) { layoutInfo.editable.keydown(options.onkeydown); }
|
5098
|
-
if (options.onpaste) { layoutInfo.editable.on('paste', options.onpaste); }
|
5099
|
-
|
5100
|
-
// callbacks for advanced features (camel)
|
5101
|
-
if (options.onToolbarClick) { layoutInfo.toolbar.click(options.onToolbarClick); }
|
5102
|
-
if (options.onChange) {
|
5103
|
-
var hChange = function () {
|
5104
|
-
editor.triggerOnChange(layoutInfo.editable);
|
5105
|
-
};
|
5106
|
-
|
5107
|
-
if (agent.isMSIE) {
|
5108
|
-
var sDomEvents = 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted';
|
5109
|
-
layoutInfo.editable.on(sDomEvents, hChange);
|
5110
|
-
} else {
|
5111
|
-
layoutInfo.editable.on('input', hChange);
|
5112
|
-
}
|
5113
|
-
}
|
5508
|
+
var history = new History(layoutInfo.editable());
|
5509
|
+
layoutInfo.editable().data('NoteHistory', history);
|
5114
5510
|
|
5115
5511
|
// All editor status will be saved on editable with jquery's data
|
5116
5512
|
// for support multiple editor with singleton object.
|
5117
|
-
layoutInfo.editable.data('callbacks', {
|
5118
|
-
|
5513
|
+
layoutInfo.editable().data('callbacks', {
|
5514
|
+
onInit: options.onInit,
|
5515
|
+
onFocus: options.onFocus,
|
5516
|
+
onBlur: options.onBlur,
|
5517
|
+
onKeydown: options.onKeydown,
|
5518
|
+
onKeyup: options.onKeyup,
|
5519
|
+
onMousedown: options.onMousedown,
|
5520
|
+
onEnter: options.onEnter,
|
5521
|
+
onPaste: options.onPaste,
|
5522
|
+
onBeforeCommand: options.onBeforeCommand,
|
5119
5523
|
onChange: options.onChange,
|
5120
|
-
onAutoSave: options.onAutoSave,
|
5121
5524
|
onImageUpload: options.onImageUpload,
|
5122
5525
|
onImageUploadError: options.onImageUploadError,
|
5123
|
-
onFileUpload: options.onFileUpload,
|
5124
|
-
onFileUploadError: options.onFileUpload,
|
5125
5526
|
onMediaDelete : options.onMediaDelete
|
5126
5527
|
});
|
5528
|
+
|
5529
|
+
// Textarea: auto filling the code before form submit.
|
5530
|
+
if (dom.isTextarea(list.head(layoutInfo.holder()))) {
|
5531
|
+
layoutInfo.holder().closest('form').submit(function () {
|
5532
|
+
var contents = layoutInfo.holder().code();
|
5533
|
+
layoutInfo.holder().val(contents);
|
5534
|
+
|
5535
|
+
// callback on submit
|
5536
|
+
if (options.onsubmit) {
|
5537
|
+
options.onsubmit(contents);
|
5538
|
+
}
|
5539
|
+
});
|
5540
|
+
}
|
5127
5541
|
};
|
5128
5542
|
|
5543
|
+
/**
|
5544
|
+
* attach jquery custom event
|
5545
|
+
*
|
5546
|
+
* @param {Object} layoutInfo - layout Informations
|
5547
|
+
*/
|
5548
|
+
this.attachCustomEvent = function (layoutInfo, options) {
|
5549
|
+
var $holder = layoutInfo.holder();
|
5550
|
+
var $editable = layoutInfo.editable();
|
5551
|
+
var callbacks = $editable.data('callbacks');
|
5552
|
+
|
5553
|
+
$editable.focus(bindCustomEvent($holder, callbacks, 'focus'));
|
5554
|
+
$editable.blur(bindCustomEvent($holder, callbacks, 'blur'));
|
5555
|
+
|
5556
|
+
$editable.keydown(function (event) {
|
5557
|
+
if (event.keyCode === key.code.ENTER) {
|
5558
|
+
bindCustomEvent($holder, callbacks, 'enter').call(this, event);
|
5559
|
+
}
|
5560
|
+
bindCustomEvent($holder, callbacks, 'keydown').call(this, event);
|
5561
|
+
});
|
5562
|
+
$editable.keyup(bindCustomEvent($holder, callbacks, 'keyup'));
|
5563
|
+
|
5564
|
+
$editable.on('mousedown', bindCustomEvent($holder, callbacks, 'mousedown'));
|
5565
|
+
$editable.on('mouseup', bindCustomEvent($holder, callbacks, 'mouseup'));
|
5566
|
+
$editable.on('scroll', bindCustomEvent($holder, callbacks, 'scroll'));
|
5567
|
+
|
5568
|
+
$editable.on('paste', bindCustomEvent($holder, callbacks, 'paste'));
|
5569
|
+
|
5570
|
+
// [workaround] for old IE - IE8 don't have input events
|
5571
|
+
if (agent.isMSIE) {
|
5572
|
+
var sDomEvents = 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted';
|
5573
|
+
$editable.on(sDomEvents, bindCustomEvent($holder, callbacks, 'change'));
|
5574
|
+
} else {
|
5575
|
+
$editable.on('input', bindCustomEvent($holder, callbacks, 'change'));
|
5576
|
+
}
|
5577
|
+
|
5578
|
+
// callbacks for advanced features (camel)
|
5579
|
+
if (!options.airMode) {
|
5580
|
+
layoutInfo.toolbar().click(bindCustomEvent($holder, callbacks, 'toolbar.click'));
|
5581
|
+
layoutInfo.popover().click(bindCustomEvent($holder, callbacks, 'popover.click'));
|
5582
|
+
}
|
5583
|
+
|
5584
|
+
// Textarea: auto filling the code before form submit.
|
5585
|
+
if (dom.isTextarea(list.head($holder))) {
|
5586
|
+
$holder.closest('form').submit(function (e) {
|
5587
|
+
bindCustomEvent($holder, callbacks, 'submit').call(this, e, $holder.code());
|
5588
|
+
});
|
5589
|
+
}
|
5590
|
+
|
5591
|
+
// fire init event
|
5592
|
+
bindCustomEvent($holder, callbacks, 'init')(layoutInfo);
|
5593
|
+
|
5594
|
+
// fire plugin init event
|
5595
|
+
for (var i = 0, len = $.summernote.plugins.length; i < len; i++) {
|
5596
|
+
if ($.isFunction($.summernote.plugins[i].init)) {
|
5597
|
+
$.summernote.plugins[i].init(layoutInfo);
|
5598
|
+
}
|
5599
|
+
}
|
5600
|
+
};
|
5601
|
+
|
5129
5602
|
this.detach = function (layoutInfo, options) {
|
5130
|
-
layoutInfo.
|
5603
|
+
layoutInfo.holder().off();
|
5604
|
+
layoutInfo.editable().off();
|
5131
5605
|
|
5132
|
-
layoutInfo.popover.off();
|
5133
|
-
layoutInfo.handle.off();
|
5134
|
-
layoutInfo.dialog.off();
|
5606
|
+
layoutInfo.popover().off();
|
5607
|
+
layoutInfo.handle().off();
|
5608
|
+
layoutInfo.dialog().off();
|
5135
5609
|
|
5136
5610
|
if (!options.airMode) {
|
5137
|
-
layoutInfo.dropzone.off();
|
5138
|
-
layoutInfo.toolbar.off();
|
5139
|
-
layoutInfo.statusbar.off();
|
5611
|
+
layoutInfo.dropzone().off();
|
5612
|
+
layoutInfo.toolbar().off();
|
5613
|
+
layoutInfo.statusbar().off();
|
5140
5614
|
}
|
5141
5615
|
};
|
5142
5616
|
};
|
@@ -5209,12 +5683,14 @@
|
|
5209
5683
|
* @param {String} content
|
5210
5684
|
*/
|
5211
5685
|
var tplPopover = function (className, content) {
|
5212
|
-
|
5686
|
+
var $popover = $('<div class="' + className + ' popover bottom in" style="display: none;">' +
|
5213
5687
|
'<div class="arrow"></div>' +
|
5214
5688
|
'<div class="popover-content">' +
|
5215
|
-
content +
|
5216
5689
|
'</div>' +
|
5217
|
-
'</div>';
|
5690
|
+
'</div>');
|
5691
|
+
|
5692
|
+
$popover.find('.popover-content').append(content);
|
5693
|
+
return $popover;
|
5218
5694
|
};
|
5219
5695
|
|
5220
5696
|
/**
|
@@ -5235,33 +5711,31 @@
|
|
5235
5711
|
'<h4 class="modal-title">' + title + '</h4>' +
|
5236
5712
|
'</div>' : ''
|
5237
5713
|
) +
|
5238
|
-
'<
|
5239
|
-
|
5240
|
-
|
5241
|
-
|
5242
|
-
) +
|
5243
|
-
'</form>' +
|
5714
|
+
'<div class="modal-body">' + body + '</div>' +
|
5715
|
+
(footer ?
|
5716
|
+
'<div class="modal-footer">' + footer + '</div>' : ''
|
5717
|
+
) +
|
5244
5718
|
'</div>' +
|
5245
5719
|
'</div>' +
|
5246
5720
|
'</div>';
|
5247
5721
|
};
|
5248
5722
|
|
5249
5723
|
var tplButtonInfo = {
|
5250
|
-
picture: function (lang) {
|
5251
|
-
return tplIconButton('
|
5724
|
+
picture: function (lang, options) {
|
5725
|
+
return tplIconButton(options.iconPrefix + 'picture-o', {
|
5252
5726
|
event: 'showImageDialog',
|
5253
5727
|
title: lang.image.image,
|
5254
5728
|
hide: true
|
5255
5729
|
});
|
5256
5730
|
},
|
5257
|
-
link: function (lang) {
|
5258
|
-
return tplIconButton('
|
5731
|
+
link: function (lang, options) {
|
5732
|
+
return tplIconButton(options.iconPrefix + 'link', {
|
5259
5733
|
event: 'showLinkDialog',
|
5260
5734
|
title: lang.link.link,
|
5261
5735
|
hide: true
|
5262
5736
|
});
|
5263
5737
|
},
|
5264
|
-
table: function (lang) {
|
5738
|
+
table: function (lang, options) {
|
5265
5739
|
var dropdown = '<ul class="note-table dropdown-menu">' +
|
5266
5740
|
'<div class="note-dimension-picker">' +
|
5267
5741
|
'<div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"></div>' +
|
@@ -5270,7 +5744,7 @@
|
|
5270
5744
|
'</div>' +
|
5271
5745
|
'<div class="note-dimension-display"> 1 x 1 </div>' +
|
5272
5746
|
'</ul>';
|
5273
|
-
return tplIconButton('
|
5747
|
+
return tplIconButton(options.iconPrefix + 'table', {
|
5274
5748
|
title: lang.table.table,
|
5275
5749
|
dropdown: dropdown
|
5276
5750
|
});
|
@@ -5286,30 +5760,49 @@
|
|
5286
5760
|
'</a></li>';
|
5287
5761
|
}, '');
|
5288
5762
|
|
5289
|
-
return tplIconButton('
|
5763
|
+
return tplIconButton(options.iconPrefix + 'magic', {
|
5290
5764
|
title: lang.style.style,
|
5291
5765
|
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
|
5292
5766
|
});
|
5293
5767
|
},
|
5294
5768
|
fontname: function (lang, options) {
|
5769
|
+
var realFontList = [];
|
5295
5770
|
var items = options.fontNames.reduce(function (memo, v) {
|
5296
5771
|
if (!agent.isFontInstalled(v) && options.fontNamesIgnoreCheck.indexOf(v) === -1) {
|
5297
5772
|
return memo;
|
5298
5773
|
}
|
5774
|
+
realFontList.push(v);
|
5299
5775
|
return memo + '<li><a data-event="fontName" href="#" data-value="' + v + '" style="font-family:\'' + v + '\'">' +
|
5300
|
-
'<i class="
|
5776
|
+
'<i class="' + options.iconPrefix + 'check"></i> ' + v +
|
5301
5777
|
'</a></li>';
|
5302
5778
|
}, '');
|
5779
|
+
|
5780
|
+
var hasDefaultFont = agent.isFontInstalled(options.defaultFontName);
|
5781
|
+
var defaultFontName = (hasDefaultFont) ? options.defaultFontName : realFontList[0];
|
5782
|
+
|
5303
5783
|
var label = '<span class="note-current-fontname">' +
|
5304
|
-
|
5784
|
+
defaultFontName +
|
5305
5785
|
'</span>';
|
5306
5786
|
return tplButton(label, {
|
5307
5787
|
title: lang.font.name,
|
5308
5788
|
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
|
5309
5789
|
});
|
5310
5790
|
},
|
5311
|
-
|
5312
|
-
var
|
5791
|
+
fontsize: function (lang, options) {
|
5792
|
+
var items = options.fontSizes.reduce(function (memo, v) {
|
5793
|
+
return memo + '<li><a data-event="fontSize" href="#" data-value="' + v + '">' +
|
5794
|
+
'<i class="fa fa-check"></i> ' + v +
|
5795
|
+
'</a></li>';
|
5796
|
+
}, '');
|
5797
|
+
|
5798
|
+
var label = '<span class="note-current-fontsize">11</span>';
|
5799
|
+
return tplButton(label, {
|
5800
|
+
title: lang.font.size,
|
5801
|
+
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
|
5802
|
+
});
|
5803
|
+
},
|
5804
|
+
color: function (lang, options) {
|
5805
|
+
var colorButtonLabel = '<i class="' + options.iconPrefix + 'font" style="color:black;background-color:yellow;"></i>';
|
5313
5806
|
var colorButton = tplButton(colorButtonLabel, {
|
5314
5807
|
className: 'note-recent-color',
|
5315
5808
|
title: lang.color.recent,
|
@@ -5344,65 +5837,83 @@
|
|
5344
5837
|
|
5345
5838
|
return colorButton + moreButton;
|
5346
5839
|
},
|
5347
|
-
bold: function (lang) {
|
5348
|
-
return tplIconButton('
|
5840
|
+
bold: function (lang, options) {
|
5841
|
+
return tplIconButton(options.iconPrefix + 'bold', {
|
5349
5842
|
event: 'bold',
|
5350
5843
|
title: lang.font.bold
|
5351
5844
|
});
|
5352
5845
|
},
|
5353
|
-
italic: function (lang) {
|
5354
|
-
return tplIconButton('
|
5846
|
+
italic: function (lang, options) {
|
5847
|
+
return tplIconButton(options.iconPrefix + 'italic', {
|
5355
5848
|
event: 'italic',
|
5356
5849
|
title: lang.font.italic
|
5357
5850
|
});
|
5358
5851
|
},
|
5359
|
-
underline: function (lang) {
|
5360
|
-
return tplIconButton('
|
5852
|
+
underline: function (lang, options) {
|
5853
|
+
return tplIconButton(options.iconPrefix + 'underline', {
|
5361
5854
|
event: 'underline',
|
5362
5855
|
title: lang.font.underline
|
5363
5856
|
});
|
5364
5857
|
},
|
5365
|
-
|
5366
|
-
return tplIconButton('fa fa-
|
5858
|
+
strikethrough: function (lang) {
|
5859
|
+
return tplIconButton('fa fa-strikethrough', {
|
5860
|
+
event: 'strikethrough',
|
5861
|
+
title: lang.font.strikethrough
|
5862
|
+
});
|
5863
|
+
},
|
5864
|
+
superscript: function (lang) {
|
5865
|
+
return tplIconButton('fa fa-superscript', {
|
5866
|
+
event: 'superscript',
|
5867
|
+
title: lang.font.superscript
|
5868
|
+
});
|
5869
|
+
},
|
5870
|
+
subscript: function (lang) {
|
5871
|
+
return tplIconButton('fa fa-subscript', {
|
5872
|
+
event: 'subscript',
|
5873
|
+
title: lang.font.subscript
|
5874
|
+
});
|
5875
|
+
},
|
5876
|
+
clear: function (lang, options) {
|
5877
|
+
return tplIconButton(options.iconPrefix + 'eraser', {
|
5367
5878
|
event: 'removeFormat',
|
5368
5879
|
title: lang.font.clear
|
5369
5880
|
});
|
5370
5881
|
},
|
5371
|
-
ul: function (lang) {
|
5372
|
-
return tplIconButton('
|
5882
|
+
ul: function (lang, options) {
|
5883
|
+
return tplIconButton(options.iconPrefix + 'list-ul', {
|
5373
5884
|
event: 'insertUnorderedList',
|
5374
5885
|
title: lang.lists.unordered
|
5375
5886
|
});
|
5376
5887
|
},
|
5377
|
-
ol: function (lang) {
|
5378
|
-
return tplIconButton('
|
5888
|
+
ol: function (lang, options) {
|
5889
|
+
return tplIconButton(options.iconPrefix + 'list-ol', {
|
5379
5890
|
event: 'insertOrderedList',
|
5380
5891
|
title: lang.lists.ordered
|
5381
5892
|
});
|
5382
5893
|
},
|
5383
|
-
paragraph: function (lang) {
|
5384
|
-
var leftButton = tplIconButton('
|
5894
|
+
paragraph: function (lang, options) {
|
5895
|
+
var leftButton = tplIconButton(options.iconPrefix + 'align-left', {
|
5385
5896
|
title: lang.paragraph.left,
|
5386
5897
|
event: 'justifyLeft'
|
5387
5898
|
});
|
5388
|
-
var centerButton = tplIconButton('
|
5899
|
+
var centerButton = tplIconButton(options.iconPrefix + 'align-center', {
|
5389
5900
|
title: lang.paragraph.center,
|
5390
5901
|
event: 'justifyCenter'
|
5391
5902
|
});
|
5392
|
-
var rightButton = tplIconButton('
|
5903
|
+
var rightButton = tplIconButton(options.iconPrefix + 'align-right', {
|
5393
5904
|
title: lang.paragraph.right,
|
5394
5905
|
event: 'justifyRight'
|
5395
5906
|
});
|
5396
|
-
var justifyButton = tplIconButton('
|
5907
|
+
var justifyButton = tplIconButton(options.iconPrefix + 'align-justify', {
|
5397
5908
|
title: lang.paragraph.justify,
|
5398
5909
|
event: 'justifyFull'
|
5399
5910
|
});
|
5400
5911
|
|
5401
|
-
var outdentButton = tplIconButton('
|
5912
|
+
var outdentButton = tplIconButton(options.iconPrefix + 'outdent', {
|
5402
5913
|
title: lang.paragraph.outdent,
|
5403
5914
|
event: 'outdent'
|
5404
5915
|
});
|
5405
|
-
var indentButton = tplIconButton('
|
5916
|
+
var indentButton = tplIconButton(options.iconPrefix + 'indent', {
|
5406
5917
|
title: lang.paragraph.indent,
|
5407
5918
|
event: 'indent'
|
5408
5919
|
});
|
@@ -5416,7 +5927,7 @@
|
|
5416
5927
|
'</div>' +
|
5417
5928
|
'</div>';
|
5418
5929
|
|
5419
|
-
return tplIconButton('
|
5930
|
+
return tplIconButton(options.iconPrefix + 'align-left', {
|
5420
5931
|
title: lang.paragraph.paragraph,
|
5421
5932
|
dropdown: dropdown
|
5422
5933
|
});
|
@@ -5424,49 +5935,49 @@
|
|
5424
5935
|
height: function (lang, options) {
|
5425
5936
|
var items = options.lineHeights.reduce(function (memo, v) {
|
5426
5937
|
return memo + '<li><a data-event="lineHeight" href="#" data-value="' + parseFloat(v) + '">' +
|
5427
|
-
'<i class="
|
5938
|
+
'<i class="' + options.iconPrefix + 'check"></i> ' + v +
|
5428
5939
|
'</a></li>';
|
5429
5940
|
}, '');
|
5430
5941
|
|
5431
|
-
return tplIconButton('
|
5942
|
+
return tplIconButton(options.iconPrefix + 'text-height', {
|
5432
5943
|
title: lang.font.height,
|
5433
5944
|
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
|
5434
5945
|
});
|
5435
5946
|
|
5436
5947
|
},
|
5437
|
-
help: function (lang) {
|
5438
|
-
return tplIconButton('
|
5948
|
+
help: function (lang, options) {
|
5949
|
+
return tplIconButton(options.iconPrefix + 'question', {
|
5439
5950
|
event: 'showHelpDialog',
|
5440
5951
|
title: lang.options.help,
|
5441
5952
|
hide: true
|
5442
5953
|
});
|
5443
5954
|
},
|
5444
|
-
fullscreen: function (lang) {
|
5445
|
-
return tplIconButton('
|
5955
|
+
fullscreen: function (lang, options) {
|
5956
|
+
return tplIconButton(options.iconPrefix + 'arrows-alt', {
|
5446
5957
|
event: 'fullscreen',
|
5447
5958
|
title: lang.options.fullscreen
|
5448
5959
|
});
|
5449
5960
|
},
|
5450
|
-
codeview: function (lang) {
|
5451
|
-
return tplIconButton('
|
5961
|
+
codeview: function (lang, options) {
|
5962
|
+
return tplIconButton(options.iconPrefix + 'code', {
|
5452
5963
|
event: 'codeview',
|
5453
5964
|
title: lang.options.codeview
|
5454
5965
|
});
|
5455
5966
|
},
|
5456
|
-
undo: function (lang) {
|
5457
|
-
return tplIconButton('
|
5967
|
+
undo: function (lang, options) {
|
5968
|
+
return tplIconButton(options.iconPrefix + 'undo', {
|
5458
5969
|
event: 'undo',
|
5459
5970
|
title: lang.history.undo
|
5460
5971
|
});
|
5461
5972
|
},
|
5462
|
-
redo: function (lang) {
|
5463
|
-
return tplIconButton('
|
5973
|
+
redo: function (lang, options) {
|
5974
|
+
return tplIconButton(options.iconPrefix + 'repeat', {
|
5464
5975
|
event: 'redo',
|
5465
5976
|
title: lang.history.redo
|
5466
5977
|
});
|
5467
5978
|
},
|
5468
|
-
hr: function (lang) {
|
5469
|
-
return tplIconButton('
|
5979
|
+
hr: function (lang, options) {
|
5980
|
+
return tplIconButton(options.iconPrefix + 'minus', {
|
5470
5981
|
event: 'insertHorizontalRule',
|
5471
5982
|
title: lang.hr.insert
|
5472
5983
|
});
|
@@ -5475,12 +5986,12 @@
|
|
5475
5986
|
|
5476
5987
|
var tplPopovers = function (lang, options) {
|
5477
5988
|
var tplLinkPopover = function () {
|
5478
|
-
var linkButton = tplIconButton('
|
5989
|
+
var linkButton = tplIconButton(options.iconPrefix + 'edit', {
|
5479
5990
|
title: lang.link.edit,
|
5480
5991
|
event: 'showLinkDialog',
|
5481
5992
|
hide: true
|
5482
5993
|
});
|
5483
|
-
var unlinkButton = tplIconButton('
|
5994
|
+
var unlinkButton = tplIconButton(options.iconPrefix + 'unlink', {
|
5484
5995
|
title: lang.link.unlink,
|
5485
5996
|
event: 'unlink'
|
5486
5997
|
});
|
@@ -5508,44 +6019,44 @@
|
|
5508
6019
|
value: '0.25'
|
5509
6020
|
});
|
5510
6021
|
|
5511
|
-
var leftButton = tplIconButton('
|
6022
|
+
var leftButton = tplIconButton(options.iconPrefix + 'align-left', {
|
5512
6023
|
title: lang.image.floatLeft,
|
5513
6024
|
event: 'floatMe',
|
5514
6025
|
value: 'left'
|
5515
6026
|
});
|
5516
|
-
var rightButton = tplIconButton('
|
6027
|
+
var rightButton = tplIconButton(options.iconPrefix + 'align-right', {
|
5517
6028
|
title: lang.image.floatRight,
|
5518
6029
|
event: 'floatMe',
|
5519
6030
|
value: 'right'
|
5520
6031
|
});
|
5521
|
-
var justifyButton = tplIconButton('
|
6032
|
+
var justifyButton = tplIconButton(options.iconPrefix + 'align-justify', {
|
5522
6033
|
title: lang.image.floatNone,
|
5523
6034
|
event: 'floatMe',
|
5524
6035
|
value: 'none'
|
5525
6036
|
});
|
5526
6037
|
|
5527
|
-
var roundedButton = tplIconButton('
|
6038
|
+
var roundedButton = tplIconButton(options.iconPrefix + 'square', {
|
5528
6039
|
title: lang.image.shapeRounded,
|
5529
6040
|
event: 'imageShape',
|
5530
6041
|
value: 'img-rounded'
|
5531
6042
|
});
|
5532
|
-
var circleButton = tplIconButton('
|
6043
|
+
var circleButton = tplIconButton(options.iconPrefix + 'circle-o', {
|
5533
6044
|
title: lang.image.shapeCircle,
|
5534
6045
|
event: 'imageShape',
|
5535
6046
|
value: 'img-circle'
|
5536
6047
|
});
|
5537
|
-
var thumbnailButton = tplIconButton('
|
6048
|
+
var thumbnailButton = tplIconButton(options.iconPrefix + 'picture-o', {
|
5538
6049
|
title: lang.image.shapeThumbnail,
|
5539
6050
|
event: 'imageShape',
|
5540
6051
|
value: 'img-thumbnail'
|
5541
6052
|
});
|
5542
|
-
var noneButton = tplIconButton('
|
6053
|
+
var noneButton = tplIconButton(options.iconPrefix + 'times', {
|
5543
6054
|
title: lang.image.shapeNone,
|
5544
6055
|
event: 'imageShape',
|
5545
6056
|
value: ''
|
5546
6057
|
});
|
5547
6058
|
|
5548
|
-
var removeButton = tplIconButton('
|
6059
|
+
var removeButton = tplIconButton(options.iconPrefix + 'trash-o', {
|
5549
6060
|
title: lang.image.remove,
|
5550
6061
|
event: 'removeMedia',
|
5551
6062
|
value: 'none'
|
@@ -5559,24 +6070,34 @@
|
|
5559
6070
|
};
|
5560
6071
|
|
5561
6072
|
var tplAirPopover = function () {
|
5562
|
-
var content = '';
|
6073
|
+
var $content = $('<div />');
|
5563
6074
|
for (var idx = 0, len = options.airPopover.length; idx < len; idx ++) {
|
5564
6075
|
var group = options.airPopover[idx];
|
5565
|
-
|
6076
|
+
|
6077
|
+
var $group = $('<div class="note-' + group[0] + ' btn-group">');
|
5566
6078
|
for (var i = 0, lenGroup = group[1].length; i < lenGroup; i++) {
|
5567
|
-
|
6079
|
+
var $button = $(tplButtonInfo[group[1][i]](lang, options));
|
6080
|
+
|
6081
|
+
$button.attr('data-name', group[1][i]);
|
6082
|
+
|
6083
|
+
$group.append($button);
|
5568
6084
|
}
|
5569
|
-
content
|
6085
|
+
$content.append($group);
|
5570
6086
|
}
|
5571
6087
|
|
5572
|
-
return tplPopover('note-air-popover', content);
|
6088
|
+
return tplPopover('note-air-popover', $content.children());
|
5573
6089
|
};
|
5574
6090
|
|
5575
|
-
|
5576
|
-
|
5577
|
-
|
5578
|
-
|
5579
|
-
|
6091
|
+
var $notePopover = $('<div class="note-popover" />');
|
6092
|
+
|
6093
|
+
$notePopover.append(tplLinkPopover());
|
6094
|
+
$notePopover.append(tplImagePopover());
|
6095
|
+
|
6096
|
+
if (options.airMode) {
|
6097
|
+
$notePopover.append(tplAirPopover());
|
6098
|
+
}
|
6099
|
+
|
6100
|
+
return $notePopover;
|
5580
6101
|
};
|
5581
6102
|
|
5582
6103
|
var tplHandles = function () {
|
@@ -5747,7 +6268,7 @@
|
|
5747
6268
|
'<div class="title">' + lang.shortcut.shortcuts + '</div>' +
|
5748
6269
|
(agent.isMac ? tplShortcutTable(lang, options) : replaceMacKeys(tplShortcutTable(lang, options))) +
|
5749
6270
|
'<p class="text-center">' +
|
5750
|
-
'<a href="//summernote.org/" target="_blank">Summernote 0.6.
|
6271
|
+
'<a href="//summernote.org/" target="_blank">Summernote 0.6.5</a> · ' +
|
5751
6272
|
'<a href="//github.com/summernote/summernote" target="_blank">Project</a> · ' +
|
5752
6273
|
'<a href="//github.com/summernote/summernote/issues" target="_blank">Issues</a>' +
|
5753
6274
|
'</p>';
|
@@ -5921,24 +6442,25 @@
|
|
5921
6442
|
$('<textarea class="note-codable"></textarea>').prependTo($editor);
|
5922
6443
|
|
5923
6444
|
//04. create Toolbar
|
5924
|
-
var
|
6445
|
+
var $toolbar = $('<div class="note-toolbar btn-toolbar" />');
|
5925
6446
|
for (var idx = 0, len = options.toolbar.length; idx < len; idx ++) {
|
5926
6447
|
var groupName = options.toolbar[idx][0];
|
5927
6448
|
var groupButtons = options.toolbar[idx][1];
|
5928
6449
|
|
5929
|
-
|
6450
|
+
var $group = $('<div class="note-' + groupName + ' btn-group" />');
|
5930
6451
|
for (var i = 0, btnLength = groupButtons.length; i < btnLength; i++) {
|
5931
6452
|
var buttonInfo = tplButtonInfo[groupButtons[i]];
|
5932
6453
|
// continue creating toolbar even if a button doesn't exist
|
5933
6454
|
if (!$.isFunction(buttonInfo)) { continue; }
|
5934
|
-
|
6455
|
+
|
6456
|
+
var $button = $(buttonInfo(langInfo, options));
|
6457
|
+
$button.attr('data-name', groupButtons[i]); // set button's alias, becuase to get button element from $toolbar
|
6458
|
+
$group.append($button);
|
5935
6459
|
}
|
5936
|
-
|
6460
|
+
$toolbar.append($group);
|
5937
6461
|
}
|
5938
|
-
|
5939
|
-
|
5940
|
-
|
5941
|
-
var $toolbar = $(toolbarHTML).prependTo($editor);
|
6462
|
+
|
6463
|
+
$toolbar.prependTo($editor);
|
5942
6464
|
var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
|
5943
6465
|
createPalette($toolbar, options);
|
5944
6466
|
createTooltip($toolbar, keyMap, 'bottom');
|
@@ -5965,6 +6487,10 @@
|
|
5965
6487
|
$holder.hide();
|
5966
6488
|
};
|
5967
6489
|
|
6490
|
+
this.hasNoteEditor = function ($holder) {
|
6491
|
+
return this.noteEditorFromHolder($holder).length > 0;
|
6492
|
+
};
|
6493
|
+
|
5968
6494
|
this.noteEditorFromHolder = function ($holder) {
|
5969
6495
|
if ($holder.hasClass('note-air-editor')) {
|
5970
6496
|
return $holder;
|
@@ -5982,10 +6508,6 @@
|
|
5982
6508
|
* @param {Object} options
|
5983
6509
|
*/
|
5984
6510
|
this.createLayout = function ($holder, options) {
|
5985
|
-
if (this.noteEditorFromHolder($holder).length) {
|
5986
|
-
return;
|
5987
|
-
}
|
5988
|
-
|
5989
6511
|
if (options.airMode) {
|
5990
6512
|
this.createLayoutByAirMode($holder, options);
|
5991
6513
|
} else {
|
@@ -5997,20 +6519,18 @@
|
|
5997
6519
|
* returns layoutInfo from holder
|
5998
6520
|
*
|
5999
6521
|
* @param {jQuery} $holder - placeholder
|
6000
|
-
* @
|
6522
|
+
* @return {Object}
|
6001
6523
|
*/
|
6002
6524
|
this.layoutInfoFromHolder = function ($holder) {
|
6003
6525
|
var $editor = this.noteEditorFromHolder($holder);
|
6004
|
-
if (!$editor.length) {
|
6005
|
-
|
6006
|
-
var layoutInfo = dom.buildLayoutInfo($editor);
|
6007
|
-
// cache all properties.
|
6008
|
-
for (var key in layoutInfo) {
|
6009
|
-
if (layoutInfo.hasOwnProperty(key)) {
|
6010
|
-
layoutInfo[key] = layoutInfo[key].call();
|
6011
|
-
}
|
6526
|
+
if (!$editor.length) {
|
6527
|
+
return;
|
6012
6528
|
}
|
6013
|
-
|
6529
|
+
|
6530
|
+
// connect $holder to $editor
|
6531
|
+
$editor.data('holder', $holder);
|
6532
|
+
|
6533
|
+
return dom.buildLayoutInfo($editor);
|
6014
6534
|
};
|
6015
6535
|
|
6016
6536
|
/**
|
@@ -6026,13 +6546,13 @@
|
|
6026
6546
|
$holder.removeClass('note-air-editor note-editable')
|
6027
6547
|
.removeAttr('id contentEditable');
|
6028
6548
|
|
6029
|
-
layoutInfo.popover.remove();
|
6030
|
-
layoutInfo.handle.remove();
|
6031
|
-
layoutInfo.dialog.remove();
|
6549
|
+
layoutInfo.popover().remove();
|
6550
|
+
layoutInfo.handle().remove();
|
6551
|
+
layoutInfo.dialog().remove();
|
6032
6552
|
} else {
|
6033
|
-
$holder.html(layoutInfo.editable.html());
|
6553
|
+
$holder.html(layoutInfo.editable().html());
|
6034
6554
|
|
6035
|
-
layoutInfo.editor.remove();
|
6555
|
+
layoutInfo.editor().remove();
|
6036
6556
|
$holder.show();
|
6037
6557
|
}
|
6038
6558
|
};
|
@@ -6079,14 +6599,17 @@
|
|
6079
6599
|
*
|
6080
6600
|
* summernote attribute
|
6081
6601
|
*
|
6082
|
-
* @mixin
|
6602
|
+
* @mixin defaults
|
6083
6603
|
* @singleton
|
6084
6604
|
*
|
6085
6605
|
*/
|
6086
6606
|
$.summernote = $.summernote || {};
|
6087
6607
|
|
6088
|
-
// extends default
|
6089
|
-
$.
|
6608
|
+
// extends default settings
|
6609
|
+
// - $.summernote.version
|
6610
|
+
// - $.summernote.options
|
6611
|
+
// - $.summernote.lang
|
6612
|
+
$.extend($.summernote, defaults);
|
6090
6613
|
|
6091
6614
|
var renderer = new Renderer();
|
6092
6615
|
var eventHandler = new EventHandler();
|
@@ -6126,7 +6649,9 @@
|
|
6126
6649
|
* * layoutInfo is a summernote layout information.
|
6127
6650
|
* * value is data-value property.
|
6128
6651
|
*/
|
6129
|
-
pluginEvents: {}
|
6652
|
+
pluginEvents: {},
|
6653
|
+
|
6654
|
+
plugins : []
|
6130
6655
|
});
|
6131
6656
|
|
6132
6657
|
/**
|
@@ -6187,6 +6712,10 @@
|
|
6187
6712
|
* @param {Object} [plugin.options] update $.summernote.options
|
6188
6713
|
*/
|
6189
6714
|
$.summernote.addPlugin = function (plugin) {
|
6715
|
+
|
6716
|
+
// save plugin list
|
6717
|
+
$.summernote.plugins.push(plugin);
|
6718
|
+
|
6190
6719
|
if (plugin.buttons) {
|
6191
6720
|
$.each(plugin.buttons, function (name, button) {
|
6192
6721
|
renderer.addButtonInfo(name, button);
|
@@ -6232,11 +6761,19 @@
|
|
6232
6761
|
* ```
|
6233
6762
|
*
|
6234
6763
|
* @member $.fn
|
6235
|
-
* @param {Object} options reference to $.summernote.options
|
6236
|
-
* @
|
6237
|
-
*/
|
6238
|
-
summernote: function (
|
6239
|
-
//
|
6764
|
+
* @param {Object|String} options reference to $.summernote.options
|
6765
|
+
* @return {this}
|
6766
|
+
*/
|
6767
|
+
summernote: function () {
|
6768
|
+
// check first argument's type
|
6769
|
+
// - {String}: External API call {{module}}.{{method}}
|
6770
|
+
// - {Object}: init options
|
6771
|
+
var type = $.type(list.head(arguments));
|
6772
|
+
var isExternalAPICalled = type === 'string';
|
6773
|
+
var isInitOptions = type === 'object';
|
6774
|
+
|
6775
|
+
// extend default options with custom user options
|
6776
|
+
var options = isInitOptions ? list.head(arguments) : {};
|
6240
6777
|
options = $.extend({}, $.summernote.options, options);
|
6241
6778
|
|
6242
6779
|
// Include langInfo in options for later use, e.g. for image drag-n-drop
|
@@ -6246,40 +6783,43 @@
|
|
6246
6783
|
this.each(function (idx, holder) {
|
6247
6784
|
var $holder = $(holder);
|
6248
6785
|
|
6249
|
-
// createLayout
|
6250
|
-
renderer.
|
6786
|
+
// if layout isn't created yet, createLayout and attach events
|
6787
|
+
if (!renderer.hasNoteEditor($holder)) {
|
6788
|
+
renderer.createLayout($holder, options);
|
6251
6789
|
|
6252
|
-
|
6253
|
-
eventHandler.attach(info, options);
|
6790
|
+
var layoutInfo = renderer.layoutInfoFromHolder($holder);
|
6254
6791
|
|
6255
|
-
|
6256
|
-
|
6257
|
-
$holder.closest('form').submit(function () {
|
6258
|
-
var contents = $holder.code();
|
6259
|
-
$holder.val(contents);
|
6792
|
+
eventHandler.attach(layoutInfo, options);
|
6793
|
+
eventHandler.attachCustomEvent(layoutInfo, options);
|
6260
6794
|
|
6261
|
-
// callback on submit
|
6262
|
-
if (options.onsubmit) {
|
6263
|
-
options.onsubmit(contents);
|
6264
|
-
}
|
6265
|
-
});
|
6266
6795
|
}
|
6267
6796
|
});
|
6268
6797
|
|
6269
|
-
// focus on first editable element
|
6270
|
-
if (this.first().length && options.focus) {
|
6271
|
-
var info = renderer.layoutInfoFromHolder(this.first());
|
6272
|
-
info.editable.focus();
|
6273
|
-
}
|
6274
|
-
|
6275
6798
|
// callback on init
|
6276
|
-
if (this.length && options.oninit) {
|
6799
|
+
if (!isExternalAPICalled && this.length && options.oninit) {
|
6277
6800
|
options.oninit();
|
6278
6801
|
}
|
6279
6802
|
|
6803
|
+
var $first = this.first();
|
6804
|
+
if ($first.length) {
|
6805
|
+
var layoutInfo = renderer.layoutInfoFromHolder($first);
|
6806
|
+
|
6807
|
+
// external API
|
6808
|
+
if (isExternalAPICalled) {
|
6809
|
+
var moduleAndMethod = list.head(list.from(arguments));
|
6810
|
+
var args = list.tail(list.from(arguments));
|
6811
|
+
|
6812
|
+
// TODO now external API only works for editor
|
6813
|
+
var params = [moduleAndMethod, layoutInfo.editable()].concat(args);
|
6814
|
+
return eventHandler.invoke.apply(eventHandler, params);
|
6815
|
+
} else if (options.focus) {
|
6816
|
+
// focus on first editable element for initialize editor
|
6817
|
+
layoutInfo.editable().focus();
|
6818
|
+
}
|
6819
|
+
}
|
6820
|
+
|
6280
6821
|
return this;
|
6281
6822
|
},
|
6282
|
-
//
|
6283
6823
|
|
6284
6824
|
/**
|
6285
6825
|
* @method
|
@@ -6297,29 +6837,36 @@
|
|
6297
6837
|
* ```
|
6298
6838
|
*
|
6299
6839
|
* @member $.fn
|
6300
|
-
* @param {String} [
|
6301
|
-
* @
|
6840
|
+
* @param {String} [html] - HTML contents(optional, set)
|
6841
|
+
* @return {this|String} - context(set) or HTML contents of note(get).
|
6302
6842
|
*/
|
6303
|
-
code: function (
|
6843
|
+
code: function (html) {
|
6304
6844
|
// get the HTML contents of note
|
6305
|
-
if (
|
6845
|
+
if (html === undefined) {
|
6306
6846
|
var $holder = this.first();
|
6307
|
-
if (!$holder.length) {
|
6308
|
-
|
6309
|
-
if (!!(info && info.editable)) {
|
6310
|
-
var isCodeview = info.editor.hasClass('codeview');
|
6311
|
-
if (isCodeview && agent.hasCodeMirror) {
|
6312
|
-
info.codable.data('cmEditor').save();
|
6313
|
-
}
|
6314
|
-
return isCodeview ? info.codable.val() : info.editable.html();
|
6847
|
+
if (!$holder.length) {
|
6848
|
+
return;
|
6315
6849
|
}
|
6316
|
-
|
6850
|
+
|
6851
|
+
var layoutInfo = renderer.layoutInfoFromHolder($holder);
|
6852
|
+
var $editable = layoutInfo && layoutInfo.editable();
|
6853
|
+
|
6854
|
+
if ($editable && $editable.length) {
|
6855
|
+
var isCodeview = eventHandler.invoke('codeview.isActivated', layoutInfo);
|
6856
|
+
eventHandler.invoke('codeview.sync', layoutInfo);
|
6857
|
+
return isCodeview ? layoutInfo.codable().val() :
|
6858
|
+
layoutInfo.editable().html();
|
6859
|
+
}
|
6860
|
+
return dom.value($holder);
|
6317
6861
|
}
|
6318
6862
|
|
6319
6863
|
// set the HTML contents of note
|
6320
6864
|
this.each(function (i, holder) {
|
6321
|
-
var
|
6322
|
-
|
6865
|
+
var layoutInfo = renderer.layoutInfoFromHolder($(holder));
|
6866
|
+
var $editable = layoutInfo && layoutInfo.editable();
|
6867
|
+
if ($editable) {
|
6868
|
+
$editable.html(html);
|
6869
|
+
}
|
6323
6870
|
});
|
6324
6871
|
|
6325
6872
|
return this;
|
@@ -6331,16 +6878,18 @@
|
|
6331
6878
|
* destroy Editor Layout and detach Key and Mouse Event
|
6332
6879
|
*
|
6333
6880
|
* @member $.fn
|
6334
|
-
* @
|
6881
|
+
* @return {this}
|
6335
6882
|
*/
|
6336
6883
|
destroy: function () {
|
6337
6884
|
this.each(function (idx, holder) {
|
6338
6885
|
var $holder = $(holder);
|
6339
6886
|
|
6340
|
-
|
6341
|
-
|
6887
|
+
if (!renderer.hasNoteEditor($holder)) {
|
6888
|
+
return;
|
6889
|
+
}
|
6342
6890
|
|
6343
|
-
var
|
6891
|
+
var info = renderer.layoutInfoFromHolder($holder);
|
6892
|
+
var options = info.editor().data('options');
|
6344
6893
|
|
6345
6894
|
eventHandler.detach(info, options);
|
6346
6895
|
renderer.removeLayout($holder, info, options);
|