tinymce-rails 3.5b3 → 3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/tinymce/rails/helper.rb +6 -4
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/plugins/autolink/editor_plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/autolink/editor_plugin_src.js +6 -6
- data/vendor/assets/javascripts/tinymce/plugins/fullscreen/editor_plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/fullscreen/editor_plugin_src.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/noneditable/editor_plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/noneditable/editor_plugin_src.js +86 -0
- data/vendor/assets/javascripts/tinymce/themes/advanced/editor_template.js +1 -1
- data/vendor/assets/javascripts/tinymce/themes/advanced/editor_template_src.js +16 -2
- data/vendor/assets/javascripts/tinymce/themes/advanced/js/image.js +4 -2
- data/vendor/assets/javascripts/tinymce/themes/advanced/skins/default/ui.css +5 -1
- data/vendor/assets/javascripts/tinymce/themes/advanced/skins/highcontrast/ui.css +5 -1
- data/vendor/assets/javascripts/tinymce/themes/advanced/skins/o2k7/ui.css +5 -1
- data/vendor/assets/javascripts/tinymce/tiny_mce.js +1 -1
- data/vendor/assets/javascripts/tinymce/tiny_mce_jquery.js +1 -1
- data/vendor/assets/javascripts/tinymce/tiny_mce_jquery_src.js +283 -137
- data/vendor/assets/javascripts/tinymce/tiny_mce_src.js +283 -118
- metadata +8 -12
@@ -6,9 +6,9 @@
|
|
6
6
|
var tinymce = {
|
7
7
|
majorVersion : '3',
|
8
8
|
|
9
|
-
minorVersion : '
|
9
|
+
minorVersion : '5',
|
10
10
|
|
11
|
-
releaseDate : '2012-03
|
11
|
+
releaseDate : '2012-05-03',
|
12
12
|
|
13
13
|
_init : function() {
|
14
14
|
var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
|
@@ -506,52 +506,64 @@
|
|
506
506
|
tinymce.create('tinymce.util.Dispatcher', {
|
507
507
|
scope : null,
|
508
508
|
listeners : null,
|
509
|
+
inDispatch: false,
|
509
510
|
|
510
|
-
Dispatcher : function(
|
511
|
-
this.scope =
|
511
|
+
Dispatcher : function(scope) {
|
512
|
+
this.scope = scope || this;
|
512
513
|
this.listeners = [];
|
513
514
|
},
|
514
515
|
|
515
|
-
add : function(
|
516
|
-
this.listeners.push({cb :
|
516
|
+
add : function(callback, scope) {
|
517
|
+
this.listeners.push({cb : callback, scope : scope || this.scope});
|
517
518
|
|
518
|
-
return
|
519
|
+
return callback;
|
519
520
|
},
|
520
521
|
|
521
|
-
addToTop : function(
|
522
|
-
this
|
522
|
+
addToTop : function(callback, scope) {
|
523
|
+
var self = this, listener = {cb : callback, scope : scope || self.scope};
|
523
524
|
|
524
|
-
|
525
|
+
// Create new listeners if addToTop is executed in a dispatch loop
|
526
|
+
if (self.inDispatch) {
|
527
|
+
self.listeners = [listener].concat(self.listeners);
|
528
|
+
} else {
|
529
|
+
self.listeners.unshift(listener);
|
530
|
+
}
|
531
|
+
|
532
|
+
return callback;
|
525
533
|
},
|
526
534
|
|
527
|
-
remove : function(
|
528
|
-
var
|
535
|
+
remove : function(callback) {
|
536
|
+
var listeners = this.listeners, output = null;
|
529
537
|
|
530
|
-
tinymce.each(
|
531
|
-
if (
|
532
|
-
|
533
|
-
|
538
|
+
tinymce.each(listeners, function(listener, i) {
|
539
|
+
if (callback == listener.cb) {
|
540
|
+
output = listener;
|
541
|
+
listeners.splice(i, 1);
|
534
542
|
return false;
|
535
543
|
}
|
536
544
|
});
|
537
545
|
|
538
|
-
return
|
546
|
+
return output;
|
539
547
|
},
|
540
548
|
|
541
549
|
dispatch : function() {
|
542
|
-
var
|
550
|
+
var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener;
|
543
551
|
|
552
|
+
self.inDispatch = true;
|
553
|
+
|
544
554
|
// Needs to be a real loop since the listener count might change while looping
|
545
555
|
// And this is also more efficient
|
546
|
-
for (i = 0; i<
|
547
|
-
|
548
|
-
|
556
|
+
for (i = 0; i < listeners.length; i++) {
|
557
|
+
listener = listeners[i];
|
558
|
+
returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]);
|
549
559
|
|
550
|
-
if (
|
560
|
+
if (returnValue === false)
|
551
561
|
break;
|
552
562
|
}
|
553
563
|
|
554
|
-
|
564
|
+
self.inDispatch = false;
|
565
|
+
|
566
|
+
return returnValue;
|
555
567
|
}
|
556
568
|
|
557
569
|
});
|
@@ -1134,12 +1146,8 @@ tinymce.util.Quirks = function(editor) {
|
|
1134
1146
|
editor.onKeyDown.add(function(editor, e) {
|
1135
1147
|
var isDelete;
|
1136
1148
|
|
1137
|
-
if (e.isDefaultPrevented()) {
|
1138
|
-
return;
|
1139
|
-
}
|
1140
|
-
|
1141
1149
|
isDelete = e.keyCode == DELETE;
|
1142
|
-
if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
|
1150
|
+
if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
|
1143
1151
|
e.preventDefault();
|
1144
1152
|
removeMergedFormatSpans(isDelete);
|
1145
1153
|
}
|
@@ -1147,33 +1155,73 @@ tinymce.util.Quirks = function(editor) {
|
|
1147
1155
|
|
1148
1156
|
editor.addCommand('Delete', function() {removeMergedFormatSpans();});
|
1149
1157
|
};
|
1150
|
-
|
1158
|
+
|
1151
1159
|
function emptyEditorWhenDeleting() {
|
1152
|
-
function
|
1153
|
-
var
|
1154
|
-
var contents = rng.cloneContents();
|
1155
|
-
body.appendChild(contents);
|
1156
|
-
return selection.serializer.serialize(body, {format: 'html'});
|
1157
|
-
}
|
1160
|
+
function getEndPointNode(rng, start) {
|
1161
|
+
var container, offset, prefix = start ? 'start' : 'end';
|
1158
1162
|
|
1159
|
-
|
1160
|
-
|
1163
|
+
container = rng[prefix + 'Container'];
|
1164
|
+
offset = rng[prefix + 'Offset'];
|
1161
1165
|
|
1162
|
-
|
1163
|
-
|
1166
|
+
// Resolve indexed container
|
1167
|
+
if (container.nodeType == 1 && container.hasChildNodes()) {
|
1168
|
+
container = container.childNodes[Math.min(start ? offset : (offset > 0 ? offset - 1 : 0), container.childNodes.length - 1)]
|
1169
|
+
}
|
1164
1170
|
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1171
|
+
return container;
|
1172
|
+
};
|
1173
|
+
|
1174
|
+
function isAtStartEndOfBody(rng, start) {
|
1175
|
+
var container, offset, root, childNode, prefix = start ? 'start' : 'end', isAfter;
|
1176
|
+
|
1177
|
+
container = rng[prefix + 'Container'];
|
1178
|
+
offset = rng[prefix + 'Offset'];
|
1179
|
+
root = dom.getRoot();
|
1180
|
+
|
1181
|
+
// Resolve indexed container
|
1182
|
+
if (container.nodeType == 1) {
|
1183
|
+
isAfter = offset >= container.childNodes.length;
|
1184
|
+
container = getEndPointNode(rng, start);
|
1185
|
+
|
1186
|
+
if (container.nodeType == 3) {
|
1187
|
+
offset = start && !isAfter ? 0 : container.nodeValue.length;
|
1188
|
+
}
|
1189
|
+
}
|
1190
|
+
|
1191
|
+
// Check if start/end is in the middle of text
|
1192
|
+
if (container.nodeType == 3 && ((start && offset > 0) || (!start && offset < container.nodeValue.length))) {
|
1193
|
+
return false;
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
// Walk up the DOM tree to see if the endpoint is at the beginning/end of body
|
1197
|
+
while (container !== root) {
|
1198
|
+
childNode = container.parentNode[start ? 'firstChild' : 'lastChild'];
|
1199
|
+
|
1200
|
+
// If first/last element is a BR then jump to it's sibling in case: <p>x<br></p>
|
1201
|
+
if (childNode.nodeName == "BR") {
|
1202
|
+
childNode = childNode[start ? 'nextSibling' : 'previousSibling'] || childNode;
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
// If the childNode isn't the container node then break in case <p><span>A</span>[X]</p>
|
1206
|
+
if (childNode !== container) {
|
1207
|
+
return false;
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
container = container.parentNode;
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
return true;
|
1214
|
+
};
|
1168
1215
|
|
1169
1216
|
editor.onKeyDown.addToTop(function(editor, e) {
|
1170
|
-
var keyCode = e.keyCode;
|
1217
|
+
var rng, keyCode = e.keyCode;
|
1171
1218
|
|
1172
|
-
if (keyCode == DELETE || keyCode == BACKSPACE) {
|
1173
|
-
|
1219
|
+
if (!e.isDefaultPrevented() && (keyCode == DELETE || keyCode == BACKSPACE)) {
|
1220
|
+
rng = selection.getRng(true);
|
1174
1221
|
|
1175
|
-
if (
|
1176
|
-
|
1222
|
+
if (isAtStartEndOfBody(rng, true) && isAtStartEndOfBody(rng, false) &&
|
1223
|
+
(rng.collapsed || dom.findCommonAncestor(getEndPointNode(rng, true), getEndPointNode(rng)) === dom.getRoot())) {
|
1224
|
+
editor.setContent('');
|
1177
1225
|
editor.nodeChanged();
|
1178
1226
|
e.preventDefault();
|
1179
1227
|
}
|
@@ -1182,14 +1230,25 @@ tinymce.util.Quirks = function(editor) {
|
|
1182
1230
|
};
|
1183
1231
|
|
1184
1232
|
function inputMethodFocus() {
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1233
|
+
if (!editor.settings.content_editable) {
|
1234
|
+
// Case 1 IME doesn't initialize if you focus the document
|
1235
|
+
dom.bind(editor.getDoc(), 'focusin', function(e) {
|
1236
|
+
selection.setRng(selection.getRng());
|
1237
|
+
});
|
1238
|
+
|
1239
|
+
// Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event
|
1240
|
+
dom.bind(editor.getDoc(), 'mousedown', function(e) {
|
1241
|
+
if (e.target == editor.getDoc().documentElement) {
|
1242
|
+
editor.getWin().focus();
|
1243
|
+
selection.setRng(selection.getRng());
|
1244
|
+
}
|
1245
|
+
});
|
1246
|
+
}
|
1188
1247
|
};
|
1189
1248
|
|
1190
1249
|
function removeHrOnBackspace() {
|
1191
1250
|
editor.onKeyDown.add(function(editor, e) {
|
1192
|
-
if (e.keyCode === BACKSPACE) {
|
1251
|
+
if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
|
1193
1252
|
if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
|
1194
1253
|
var node = selection.getNode();
|
1195
1254
|
var previousSibling = node.previousSibling;
|
@@ -1322,7 +1381,7 @@ tinymce.util.Quirks = function(editor) {
|
|
1322
1381
|
|
1323
1382
|
function disableBackspaceIntoATable() {
|
1324
1383
|
editor.onKeyDown.add(function(editor, e) {
|
1325
|
-
if (e.keyCode === BACKSPACE) {
|
1384
|
+
if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
|
1326
1385
|
if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
|
1327
1386
|
var previousSibling = selection.getNode().previousSibling;
|
1328
1387
|
if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
|
@@ -1410,12 +1469,8 @@ tinymce.util.Quirks = function(editor) {
|
|
1410
1469
|
editor.onKeyDown.add(function(editor, e) {
|
1411
1470
|
var isDelete, rng, container, offset, brElm, sibling, collapsed;
|
1412
1471
|
|
1413
|
-
if (e.isDefaultPrevented()) {
|
1414
|
-
return;
|
1415
|
-
}
|
1416
|
-
|
1417
1472
|
isDelete = e.keyCode == DELETE;
|
1418
|
-
if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
|
1473
|
+
if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
|
1419
1474
|
rng = selection.getRng();
|
1420
1475
|
container = rng.startContainer;
|
1421
1476
|
offset = rng.startOffset;
|
@@ -1455,7 +1510,7 @@ tinymce.util.Quirks = function(editor) {
|
|
1455
1510
|
editor.onKeyDown.add(function(editor, e) {
|
1456
1511
|
var rng, container, offset, root, parent;
|
1457
1512
|
|
1458
|
-
if (e.keyCode != VK.BACKSPACE) {
|
1513
|
+
if (e.isDefaultPrevented() || e.keyCode != VK.BACKSPACE) {
|
1459
1514
|
return;
|
1460
1515
|
}
|
1461
1516
|
|
@@ -1469,7 +1524,7 @@ tinymce.util.Quirks = function(editor) {
|
|
1469
1524
|
return;
|
1470
1525
|
}
|
1471
1526
|
|
1472
|
-
while (parent && parent.parentNode.firstChild == parent && parent.parentNode != root) {
|
1527
|
+
while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) {
|
1473
1528
|
parent = parent.parentNode;
|
1474
1529
|
}
|
1475
1530
|
|
@@ -1547,7 +1602,7 @@ tinymce.util.Quirks = function(editor) {
|
|
1547
1602
|
|
1548
1603
|
function deleteImageOnBackSpace() {
|
1549
1604
|
editor.onKeyDown.add(function(editor, e) {
|
1550
|
-
if (e.keyCode == 8 && selection.getNode().nodeName == 'IMG') {
|
1605
|
+
if (!e.isDefaultPrevented() && e.keyCode == 8 && selection.getNode().nodeName == 'IMG') {
|
1551
1606
|
e.preventDefault();
|
1552
1607
|
editor.undoManager.beforeChange();
|
1553
1608
|
dom.remove(selection.getNode());
|
@@ -1559,12 +1614,12 @@ tinymce.util.Quirks = function(editor) {
|
|
1559
1614
|
// All browsers
|
1560
1615
|
disableBackspaceIntoATable();
|
1561
1616
|
removeBlockQuoteOnBackSpace();
|
1617
|
+
emptyEditorWhenDeleting();
|
1562
1618
|
|
1563
1619
|
// WebKit
|
1564
1620
|
if (tinymce.isWebKit) {
|
1565
1621
|
keepInlineElementOnDeleteBackspace();
|
1566
1622
|
cleanupStylesWhenDeleting();
|
1567
|
-
emptyEditorWhenDeleting();
|
1568
1623
|
inputMethodFocus();
|
1569
1624
|
selectControlElements();
|
1570
1625
|
|
@@ -1577,7 +1632,6 @@ tinymce.util.Quirks = function(editor) {
|
|
1577
1632
|
// IE
|
1578
1633
|
if (tinymce.isIE) {
|
1579
1634
|
removeHrOnBackspace();
|
1580
|
-
emptyEditorWhenDeleting();
|
1581
1635
|
ensureBodyHasRoleApplication();
|
1582
1636
|
addNewLinesBeforeBrInPre();
|
1583
1637
|
removePreSerializedStylesWhenSelectingControls();
|
@@ -3459,7 +3513,7 @@ tinymce.html.Styles = function(settings, schema) {
|
|
3459
3513
|
self.parse = function(html, args) {
|
3460
3514
|
var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate,
|
3461
3515
|
blockElements, startWhiteSpaceRegExp, invalidChildren = [], isInWhiteSpacePreservedElement,
|
3462
|
-
endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName;
|
3516
|
+
endWhiteSpaceRegExp, allWhiteSpaceRegExp, isAllWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName;
|
3463
3517
|
|
3464
3518
|
args = args || {};
|
3465
3519
|
matchedNodes = {};
|
@@ -3474,6 +3528,7 @@ tinymce.html.Styles = function(settings, schema) {
|
|
3474
3528
|
startWhiteSpaceRegExp = /^[ \t\r\n]+/;
|
3475
3529
|
endWhiteSpaceRegExp = /[ \t\r\n]+$/;
|
3476
3530
|
allWhiteSpaceRegExp = /[ \t\r\n]+/g;
|
3531
|
+
isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/;
|
3477
3532
|
|
3478
3533
|
function addRootBlocks() {
|
3479
3534
|
var node = rootNode.firstChild, next, rootBlockNode;
|
@@ -3626,10 +3681,12 @@ tinymce.html.Styles = function(settings, schema) {
|
|
3626
3681
|
if (elementRule) {
|
3627
3682
|
if (blockElements[name]) {
|
3628
3683
|
if (!isInWhiteSpacePreservedElement) {
|
3629
|
-
// Trim whitespace
|
3630
|
-
|
3684
|
+
// Trim whitespace of the first node in a block
|
3685
|
+
textNode = node.firstChild;
|
3686
|
+
if (textNode && textNode.type === 3) {
|
3631
3687
|
text = textNode.value.replace(startWhiteSpaceRegExp, '');
|
3632
3688
|
|
3689
|
+
// Any characters left after trim or should we remove it
|
3633
3690
|
if (text.length > 0) {
|
3634
3691
|
textNode.value = text;
|
3635
3692
|
textNode = textNode.next;
|
@@ -3638,12 +3695,27 @@ tinymce.html.Styles = function(settings, schema) {
|
|
3638
3695
|
textNode.remove();
|
3639
3696
|
textNode = sibling;
|
3640
3697
|
}
|
3698
|
+
|
3699
|
+
// Remove any pure whitespace siblings
|
3700
|
+
while (textNode && textNode.type === 3) {
|
3701
|
+
text = textNode.value;
|
3702
|
+
sibling = textNode.next;
|
3703
|
+
|
3704
|
+
if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
|
3705
|
+
textNode.remove();
|
3706
|
+
textNode = sibling;
|
3707
|
+
}
|
3708
|
+
|
3709
|
+
textNode = sibling;
|
3710
|
+
}
|
3641
3711
|
}
|
3642
3712
|
|
3643
|
-
// Trim whitespace
|
3644
|
-
|
3713
|
+
// Trim whitespace of the last node in a block
|
3714
|
+
textNode = node.lastChild;
|
3715
|
+
if (textNode && textNode.type === 3) {
|
3645
3716
|
text = textNode.value.replace(endWhiteSpaceRegExp, '');
|
3646
3717
|
|
3718
|
+
// Any characters left after trim or should we remove it
|
3647
3719
|
if (text.length > 0) {
|
3648
3720
|
textNode.value = text;
|
3649
3721
|
textNode = textNode.prev;
|
@@ -3652,6 +3724,19 @@ tinymce.html.Styles = function(settings, schema) {
|
|
3652
3724
|
textNode.remove();
|
3653
3725
|
textNode = sibling;
|
3654
3726
|
}
|
3727
|
+
|
3728
|
+
// Remove any pure whitespace siblings
|
3729
|
+
while (textNode && textNode.type === 3) {
|
3730
|
+
text = textNode.value;
|
3731
|
+
sibling = textNode.prev;
|
3732
|
+
|
3733
|
+
if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
|
3734
|
+
textNode.remove();
|
3735
|
+
textNode = sibling;
|
3736
|
+
}
|
3737
|
+
|
3738
|
+
textNode = sibling;
|
3739
|
+
}
|
3655
3740
|
}
|
3656
3741
|
}
|
3657
3742
|
|
@@ -4532,7 +4617,11 @@ tinymce.dom = {};
|
|
4532
4617
|
return self.bind(target, events instanceof Array ? events.join(' ') : events, func, scope);
|
4533
4618
|
};
|
4534
4619
|
|
4535
|
-
self.remove = function(target, events, func) {
|
4620
|
+
self.remove = function(target, events, func, scope) {
|
4621
|
+
if (!target) {
|
4622
|
+
return self;
|
4623
|
+
}
|
4624
|
+
|
4536
4625
|
// Old API supported direct ID assignment
|
4537
4626
|
if (typeof(target) === "string") {
|
4538
4627
|
target = document.getElementById(target);
|
@@ -4540,7 +4629,7 @@ tinymce.dom = {};
|
|
4540
4629
|
|
4541
4630
|
// Old API supported multiple targets
|
4542
4631
|
if (target instanceof Array) {
|
4543
|
-
var i = target;
|
4632
|
+
var i = target.length;
|
4544
4633
|
|
4545
4634
|
while (i--) {
|
4546
4635
|
self.remove(target[i], events, func, scope);
|
@@ -8967,6 +9056,29 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
8967
9056
|
return index;
|
8968
9057
|
};
|
8969
9058
|
|
9059
|
+
function normalizeTableCellSelection(rng) {
|
9060
|
+
function moveEndPoint(start) {
|
9061
|
+
var container, offset, childNodes, prefix = start ? 'start' : 'end';
|
9062
|
+
|
9063
|
+
container = rng[prefix + 'Container'];
|
9064
|
+
offset = rng[prefix + 'Offset'];
|
9065
|
+
|
9066
|
+
if (container.nodeType == 1 && container.nodeName == "TR") {
|
9067
|
+
childNodes = container.childNodes;
|
9068
|
+
container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
|
9069
|
+
if (container) {
|
9070
|
+
offset = start ? 0 : container.childNodes.length;
|
9071
|
+
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
9072
|
+
}
|
9073
|
+
}
|
9074
|
+
};
|
9075
|
+
|
9076
|
+
moveEndPoint(true);
|
9077
|
+
moveEndPoint();
|
9078
|
+
|
9079
|
+
return rng;
|
9080
|
+
};
|
9081
|
+
|
8970
9082
|
function getLocation() {
|
8971
9083
|
var rng = t.getRng(true), root = dom.getRoot(), bookmark = {};
|
8972
9084
|
|
@@ -9061,13 +9173,8 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9061
9173
|
if (name == 'IMG')
|
9062
9174
|
return {name : name, index : findIndex(name, element)};
|
9063
9175
|
|
9064
|
-
// Can't insert a node into the root of document WebKit defaults to document
|
9065
|
-
if (rng.startContainer.nodeType == 9) {
|
9066
|
-
return;
|
9067
|
-
}
|
9068
|
-
|
9069
9176
|
// W3C method
|
9070
|
-
rng2 = rng.cloneRange();
|
9177
|
+
rng2 = normalizeTableCellSelection(rng.cloneRange());
|
9071
9178
|
|
9072
9179
|
// Insert end marker
|
9073
9180
|
if (!collapsed) {
|
@@ -9075,6 +9182,7 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9075
9182
|
rng2.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_end', style : styles}, chr));
|
9076
9183
|
}
|
9077
9184
|
|
9185
|
+
rng = normalizeTableCellSelection(rng);
|
9078
9186
|
rng.collapse(true);
|
9079
9187
|
rng.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_start', style : styles}, chr));
|
9080
9188
|
}
|
@@ -9299,48 +9407,58 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9299
9407
|
},
|
9300
9408
|
|
9301
9409
|
getRng : function(w3c) {
|
9302
|
-
var
|
9410
|
+
var self = this, selection, rng, elm, doc = self.win.document;
|
9303
9411
|
|
9304
9412
|
// Found tridentSel object then we need to use that one
|
9305
|
-
if (w3c &&
|
9306
|
-
return
|
9413
|
+
if (w3c && self.tridentSel) {
|
9414
|
+
return self.tridentSel.getRangeAt(0);
|
9415
|
+
}
|
9307
9416
|
|
9308
9417
|
try {
|
9309
|
-
if (
|
9310
|
-
|
9418
|
+
if (selection = self.getSel()) {
|
9419
|
+
rng = selection.rangeCount > 0 ? selection.getRangeAt(0) : (selection.createRange ? selection.createRange() : doc.createRange());
|
9420
|
+
}
|
9311
9421
|
} catch (ex) {
|
9312
9422
|
// IE throws unspecified error here if TinyMCE is placed in a frame/iframe
|
9313
9423
|
}
|
9314
9424
|
|
9315
9425
|
// We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet
|
9316
|
-
if (tinymce.isIE &&
|
9426
|
+
if (tinymce.isIE && rng && rng.setStart && doc.selection.createRange().item) {
|
9317
9427
|
elm = doc.selection.createRange().item(0);
|
9318
|
-
|
9319
|
-
|
9320
|
-
|
9428
|
+
rng = doc.createRange();
|
9429
|
+
rng.setStartBefore(elm);
|
9430
|
+
rng.setEndAfter(elm);
|
9321
9431
|
}
|
9322
9432
|
|
9323
9433
|
// No range found then create an empty one
|
9324
9434
|
// This can occur when the editor is placed in a hidden container element on Gecko
|
9325
9435
|
// Or on IE when there was an exception
|
9326
|
-
if (!
|
9327
|
-
|
9436
|
+
if (!rng) {
|
9437
|
+
rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
|
9438
|
+
}
|
9328
9439
|
|
9329
|
-
|
9330
|
-
|
9440
|
+
// If range is at start of document then move it to start of body
|
9441
|
+
if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
|
9442
|
+
elm = self.dom.getRoot();
|
9443
|
+
rng.setStart(elm, 0);
|
9444
|
+
rng.setEnd(elm, 0);
|
9445
|
+
}
|
9446
|
+
|
9447
|
+
if (self.selectedRange && self.explicitRange) {
|
9448
|
+
if (rng.compareBoundaryPoints(rng.START_TO_START, self.selectedRange) === 0 && rng.compareBoundaryPoints(rng.END_TO_END, self.selectedRange) === 0) {
|
9331
9449
|
// Safari, Opera and Chrome only ever select text which causes the range to change.
|
9332
9450
|
// This lets us use the originally set range if the selection hasn't been changed by the user.
|
9333
|
-
|
9451
|
+
rng = self.explicitRange;
|
9334
9452
|
} else {
|
9335
|
-
|
9336
|
-
|
9453
|
+
self.selectedRange = null;
|
9454
|
+
self.explicitRange = null;
|
9337
9455
|
}
|
9338
9456
|
}
|
9339
9457
|
|
9340
|
-
return
|
9458
|
+
return rng;
|
9341
9459
|
},
|
9342
9460
|
|
9343
|
-
setRng : function(r) {
|
9461
|
+
setRng : function(r, forward) {
|
9344
9462
|
var s, t = this;
|
9345
9463
|
|
9346
9464
|
if (!t.tridentSel) {
|
@@ -9356,6 +9474,13 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9356
9474
|
}
|
9357
9475
|
|
9358
9476
|
s.addRange(r);
|
9477
|
+
|
9478
|
+
// Forward is set to false and we have an extend function
|
9479
|
+
if (forward === false && s.extend) {
|
9480
|
+
s.collapse(r.endContainer, r.endOffset);
|
9481
|
+
s.extend(r.startContainer, r.startOffset);
|
9482
|
+
}
|
9483
|
+
|
9359
9484
|
// adding range isn't always successful so we need to check range count otherwise an exception can occur
|
9360
9485
|
t.selectedRange = s.rangeCount > 0 ? s.getRangeAt(0) : null;
|
9361
9486
|
}
|
@@ -9471,12 +9596,41 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9471
9596
|
return bl;
|
9472
9597
|
},
|
9473
9598
|
|
9599
|
+
isForward: function(){
|
9600
|
+
var dom = this.dom, sel = this.getSel(), anchorRange, focusRange;
|
9601
|
+
|
9602
|
+
// No support for selection direction then always return true
|
9603
|
+
if (!sel || sel.anchorNode == null || sel.focusNode == null) {
|
9604
|
+
return true;
|
9605
|
+
}
|
9606
|
+
|
9607
|
+
anchorRange = dom.createRng();
|
9608
|
+
anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
|
9609
|
+
anchorRange.collapse(true);
|
9610
|
+
|
9611
|
+
focusRange = dom.createRng();
|
9612
|
+
focusRange.setStart(sel.focusNode, sel.focusOffset);
|
9613
|
+
focusRange.collapse(true);
|
9614
|
+
|
9615
|
+
return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
|
9616
|
+
},
|
9617
|
+
|
9474
9618
|
normalize : function() {
|
9475
|
-
var self = this, rng, normalized, collapsed;
|
9619
|
+
var self = this, rng, normalized, collapsed, node, sibling;
|
9476
9620
|
|
9477
9621
|
function normalizeEndPoint(start) {
|
9478
9622
|
var container, offset, walker, dom = self.dom, body = dom.getRoot(), node, nonEmptyElementsMap, nodeName;
|
9479
9623
|
|
9624
|
+
function hasBrBeforeAfter(node, left) {
|
9625
|
+
var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body);
|
9626
|
+
|
9627
|
+
while (node = walker[left ? 'prev' : 'next']()) {
|
9628
|
+
if (node.nodeName === "BR") {
|
9629
|
+
return true;
|
9630
|
+
}
|
9631
|
+
}
|
9632
|
+
};
|
9633
|
+
|
9480
9634
|
// Walks the dom left/right to find a suitable text node to move the endpoint into
|
9481
9635
|
// It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG
|
9482
9636
|
function findTextNodeRelative(left, startNode) {
|
@@ -9517,7 +9671,7 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9517
9671
|
|
9518
9672
|
// If the container is a document move it to the body element
|
9519
9673
|
if (container.nodeType === 9) {
|
9520
|
-
container =
|
9674
|
+
container = dom.getRoot();
|
9521
9675
|
offset = 0;
|
9522
9676
|
}
|
9523
9677
|
|
@@ -9540,7 +9694,7 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9540
9694
|
offset = 0;
|
9541
9695
|
|
9542
9696
|
// Don't walk into elements that doesn't have any child nodes like a IMG
|
9543
|
-
if (container.hasChildNodes()) {
|
9697
|
+
if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) {
|
9544
9698
|
// Walk the DOM to find a text node to place the caret at or a BR
|
9545
9699
|
node = container;
|
9546
9700
|
walker = new TreeWalker(container, body);
|
@@ -9572,7 +9726,6 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9572
9726
|
}
|
9573
9727
|
}
|
9574
9728
|
|
9575
|
-
|
9576
9729
|
// Lean the caret to the left if possible
|
9577
9730
|
if (collapsed) {
|
9578
9731
|
// So this: <b>x</b><i>|x</i>
|
@@ -9586,8 +9739,11 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9586
9739
|
// So this: <i><b></b><i>|<br></i>
|
9587
9740
|
// Becomes: <i><b>|</b><i><br></i>
|
9588
9741
|
// Seems that only gecko has issues with this
|
9589
|
-
if (container.nodeType === 1
|
9590
|
-
|
9742
|
+
if (container.nodeType === 1) {
|
9743
|
+
node = container.childNodes[offset];
|
9744
|
+
if(node && node.nodeName === 'BR' && !hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) {
|
9745
|
+
findTextNodeRelative(true, container.childNodes[offset]);
|
9746
|
+
}
|
9591
9747
|
}
|
9592
9748
|
}
|
9593
9749
|
|
@@ -9603,9 +9759,6 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9603
9759
|
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
9604
9760
|
};
|
9605
9761
|
|
9606
|
-
// TODO:
|
9607
|
-
// Retain selection direction.
|
9608
|
-
|
9609
9762
|
// Normalize only on non IE browsers for now
|
9610
9763
|
if (tinymce.isIE)
|
9611
9764
|
return;
|
@@ -9627,7 +9780,7 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9627
9780
|
}
|
9628
9781
|
|
9629
9782
|
//console.log(self.dom.dumpRng(rng));
|
9630
|
-
self.setRng(rng);
|
9783
|
+
self.setRng(rng, self.isForward());
|
9631
9784
|
}
|
9632
9785
|
},
|
9633
9786
|
|
@@ -9771,13 +9924,13 @@ window.tinymce.dom.Sizzle = Sizzle;
|
|
9771
9924
|
}
|
9772
9925
|
});
|
9773
9926
|
|
9774
|
-
// Remove internal classes mceItem<..>
|
9927
|
+
// Remove internal classes mceItem<..> or mceSelected
|
9775
9928
|
htmlParser.addAttributeFilter('class', function(nodes, name) {
|
9776
9929
|
var i = nodes.length, node, value;
|
9777
9930
|
|
9778
9931
|
while (i--) {
|
9779
9932
|
node = nodes[i];
|
9780
|
-
value = node.attr('class').replace(
|
9933
|
+
value = node.attr('class').replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g, '');
|
9781
9934
|
node.attr('class', value.length > 0 ? value : null);
|
9782
9935
|
}
|
9783
9936
|
});
|
@@ -10851,8 +11004,8 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
|
|
10851
11004
|
update : function() {
|
10852
11005
|
var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
|
10853
11006
|
|
10854
|
-
tw = s.max_width ? Math.min(tb.
|
10855
|
-
th = s.max_height ? Math.min(tb.
|
11007
|
+
tw = s.max_width ? Math.min(tb.offsetWidth, s.max_width) : tb.offsetWidth;
|
11008
|
+
th = s.max_height ? Math.min(tb.offsetHeight, s.max_height) : tb.offsetHeight;
|
10856
11009
|
|
10857
11010
|
if (!DOM.boxModel)
|
10858
11011
|
t.element.setStyles({width : tw + 2, height : th + 2});
|
@@ -11397,7 +11550,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
|
|
11397
11550
|
m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
|
11398
11551
|
menu_line : 1,
|
11399
11552
|
'class' : t.classPrefix + 'Menu mceNoIcons',
|
11400
|
-
max_width :
|
11553
|
+
max_width : 250,
|
11401
11554
|
max_height : 150
|
11402
11555
|
});
|
11403
11556
|
|
@@ -13515,7 +13668,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
|
|
13515
13668
|
},
|
13516
13669
|
|
13517
13670
|
hide : function() {
|
13518
|
-
var self = this, doc =
|
13671
|
+
var self = this, doc = self.getDoc();
|
13519
13672
|
|
13520
13673
|
// Fixed bug where IE has a blinking cursor left from the editor
|
13521
13674
|
if (isIE && doc)
|
@@ -14642,9 +14795,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
|
|
14642
14795
|
// Override justify commands
|
14643
14796
|
'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) {
|
14644
14797
|
var name = 'align' + command.substring(7);
|
14645
|
-
|
14646
|
-
// and right align buttons can be active. This could occur when selected nodes have align right and the parent has align left.
|
14647
|
-
var nodes = selection.isCollapsed() ? [selection.getNode()] : selection.getSelectedBlocks();
|
14798
|
+
var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks();
|
14648
14799
|
var matches = tinymce.map(nodes, function(node) {
|
14649
14800
|
return !!formatter.matchNode(node, name);
|
14650
14801
|
});
|
@@ -14926,7 +15077,7 @@ tinymce.ForceBlocks = function(editor) {
|
|
14926
15077
|
var settings = editor.settings, dom = editor.dom, selection = editor.selection, blockElements = editor.schema.getBlockElements();
|
14927
15078
|
|
14928
15079
|
function addRootBlocks() {
|
14929
|
-
var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF;
|
15080
|
+
var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF, wrapped;
|
14930
15081
|
|
14931
15082
|
if (!node || node.nodeType !== 1 || !settings.forced_root_block)
|
14932
15083
|
return;
|
@@ -14972,6 +15123,7 @@ tinymce.ForceBlocks = function(editor) {
|
|
14972
15123
|
if (!rootBlockNode) {
|
14973
15124
|
rootBlockNode = dom.create(settings.forced_root_block);
|
14974
15125
|
node.parentNode.insertBefore(rootBlockNode, node);
|
15126
|
+
wrapped = true;
|
14975
15127
|
}
|
14976
15128
|
|
14977
15129
|
tempNode = node;
|
@@ -15003,13 +15155,16 @@ tinymce.ForceBlocks = function(editor) {
|
|
15003
15155
|
}
|
15004
15156
|
}
|
15005
15157
|
|
15006
|
-
|
15158
|
+
// Only trigger nodeChange when we wrapped nodes to prevent a forever loop
|
15159
|
+
if (wrapped) {
|
15160
|
+
editor.nodeChanged();
|
15161
|
+
}
|
15007
15162
|
};
|
15008
15163
|
|
15009
15164
|
// Force root blocks
|
15010
15165
|
if (settings.forced_root_block) {
|
15011
15166
|
editor.onKeyUp.add(addRootBlocks);
|
15012
|
-
editor.
|
15167
|
+
editor.onNodeChange.add(addRootBlocks);
|
15013
15168
|
}
|
15014
15169
|
};
|
15015
15170
|
|
@@ -15105,6 +15260,8 @@ tinymce.ForceBlocks = function(editor) {
|
|
15105
15260
|
if (v = ed.getParam('skin_variant'))
|
15106
15261
|
s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);
|
15107
15262
|
|
15263
|
+
s['class'] += ed.settings.directionality == "rtl" ? ' mceRtl' : '';
|
15264
|
+
|
15108
15265
|
id = t.prefix + id;
|
15109
15266
|
cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;
|
15110
15267
|
c = t.controls[id] = new cls(id, s);
|
@@ -16218,9 +16375,8 @@ tinymce.ForceBlocks = function(editor) {
|
|
16218
16375
|
if (startContainer != endContainer) {
|
16219
16376
|
// WebKit will render the table incorrectly if we wrap a TD in a SPAN so lets see if the can use the first child instead
|
16220
16377
|
// This will happen if you tripple click a table cell and use remove formatting
|
16221
|
-
|
16222
|
-
|
16223
|
-
startContainer = node;
|
16378
|
+
if (/^(TR|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) {
|
16379
|
+
startContainer = (startContainer.nodeName == "TD" ? startContainer.firstChild : startContainer.firstChild.firstChild) || startContainer;
|
16224
16380
|
}
|
16225
16381
|
|
16226
16382
|
// Wrap start/end nodes in span element since these might be cloned/moved
|
@@ -17381,6 +17537,15 @@ tinymce.ForceBlocks = function(editor) {
|
|
17381
17537
|
}
|
17382
17538
|
});
|
17383
17539
|
|
17540
|
+
// Remove bogus state if they got filled by contents using editor.selection.setContent
|
17541
|
+
selection.onSetContent.add(function() {
|
17542
|
+
dom.getParent(selection.getStart(), function(node) {
|
17543
|
+
if (node.id !== caretContainerId && dom.getAttrib(node, 'data-mce-bogus') && !dom.isEmpty(node)) {
|
17544
|
+
dom.setAttrib(node, 'data-mce-bogus', null);
|
17545
|
+
}
|
17546
|
+
});
|
17547
|
+
});
|
17548
|
+
|
17384
17549
|
self._hasCaretEvents = true;
|
17385
17550
|
}
|
17386
17551
|
|