summernote-rails 0.6.2.1 → 0.6.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|