tinymce-rails 4.1.0 → 4.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/source/tinymce/tinymce.jquery.js +1807 -1807
- data/app/assets/source/tinymce/tinymce.js +2305 -2195
- data/lib/tinymce/rails/engine.rb +1 -1
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/contextmenu/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/fullpage/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/legacyoutput/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/spellchecker/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/textcolor/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.ie7.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/themes/modern/theme.js +1 -1
- data/vendor/assets/javascripts/tinymce/tinymce.jquery.js +10 -10
- data/vendor/assets/javascripts/tinymce/tinymce.js +11 -11
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ed252e5480fab2a3bbb1983a01e1f957a35ab4e
|
4
|
+
data.tar.gz: ee8dea59d4d5816febe74868d41a8d3704e1bf96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 640e3793e032a0930269af99cb9e087bb6c37e06a72ac7c96c2db5a307d740c58148424711c4c12621fa7b22385d1e97fc4a1fe777f5ef86b07c4f84eff8ff10
|
7
|
+
data.tar.gz: f52b7cdb924065fa538253e6f0fa13edb623274b86e068fca7aed80a2bc8bc8b24b036f067074d22e5beb8670abd8ca7297c54aabb9e2ca0baf91eb9eee45f5d
|
@@ -1,4 +1,4 @@
|
|
1
|
-
// 4.1.
|
1
|
+
// 4.1.2 (2014-07-15)
|
2
2
|
|
3
3
|
/**
|
4
4
|
* Compiled inline version. (Library mode)
|
@@ -744,10 +744,13 @@ define("tinymce/util/Tools", [], function() {
|
|
744
744
|
* @return {Array} Array object based in input.
|
745
745
|
*/
|
746
746
|
function toArray(obj) {
|
747
|
-
var array =
|
747
|
+
var array = obj, i, l;
|
748
748
|
|
749
|
-
|
750
|
-
array
|
749
|
+
if (!isArray(obj)) {
|
750
|
+
array = [];
|
751
|
+
for (i = 0, l = obj.length; i < l; i++) {
|
752
|
+
array[i] = obj[i];
|
753
|
+
}
|
751
754
|
}
|
752
755
|
|
753
756
|
return array;
|
@@ -1327,9 +1330,6 @@ define("tinymce/Env", [], function() {
|
|
1327
1330
|
*
|
1328
1331
|
* License: http://www.tinymce.com/license
|
1329
1332
|
* Contributing: http://www.tinymce.com/contributing
|
1330
|
-
*
|
1331
|
-
* Some of this logic is based on jQuery code that is released under
|
1332
|
-
* MIT license that grants us to sublicense it under LGPL.
|
1333
1333
|
*/
|
1334
1334
|
|
1335
1335
|
/**
|
@@ -1342,7 +1342,6 @@ define("tinymce/Env", [], function() {
|
|
1342
1342
|
* - Event binding
|
1343
1343
|
*
|
1344
1344
|
* This is not currently implemented:
|
1345
|
-
* - Offset
|
1346
1345
|
* - Dimension
|
1347
1346
|
* - Ajax
|
1348
1347
|
* - Animation
|
@@ -1391,8 +1390,10 @@ define("tinymce/dom/DomQuery", [
|
|
1391
1390
|
var i;
|
1392
1391
|
|
1393
1392
|
if (isString(sourceItem)) {
|
1394
|
-
sourceItem = createFragment(sourceItem);
|
1393
|
+
sourceItem = createFragment(sourceItem, getElementDocument(targetNodes[0]));
|
1395
1394
|
} else if (sourceItem.length && !sourceItem.nodeType) {
|
1395
|
+
sourceItem = DomQuery.makeArray(sourceItem);
|
1396
|
+
|
1396
1397
|
if (reverse) {
|
1397
1398
|
for (i = sourceItem.length - 1; i >= 0; i--) {
|
1398
1399
|
domManipulate(targetNodes, sourceItem[i], callback, reverse);
|
@@ -1406,9 +1407,11 @@ define("tinymce/dom/DomQuery", [
|
|
1406
1407
|
return targetNodes;
|
1407
1408
|
}
|
1408
1409
|
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1410
|
+
if (sourceItem.nodeType) {
|
1411
|
+
i = targetNodes.length;
|
1412
|
+
while (i--) {
|
1413
|
+
callback.call(targetNodes[i], sourceItem);
|
1414
|
+
}
|
1412
1415
|
}
|
1413
1416
|
|
1414
1417
|
return targetNodes;
|
@@ -1446,62 +1449,11 @@ define("tinymce/dom/DomQuery", [
|
|
1446
1449
|
'class': 'className',
|
1447
1450
|
'readonly': 'readOnly'
|
1448
1451
|
};
|
1452
|
+
var cssFix = {
|
1453
|
+
float: 'cssFloat'
|
1454
|
+
};
|
1449
1455
|
|
1450
|
-
var
|
1451
|
-
|
1452
|
-
function appendHooks(target, hooks) {
|
1453
|
-
each(hooks, function(key, value) {
|
1454
|
-
each(key.split(' '), function() {
|
1455
|
-
target[this] = value;
|
1456
|
-
});
|
1457
|
-
});
|
1458
|
-
}
|
1459
|
-
|
1460
|
-
if (Env.ie && Env.ie <= 7) {
|
1461
|
-
appendHooks(attrGetHooks, {
|
1462
|
-
maxlength: function(elm, value) {
|
1463
|
-
value = elm.maxLength;
|
1464
|
-
|
1465
|
-
if (value === 0x7fffffff) {
|
1466
|
-
return undef;
|
1467
|
-
}
|
1468
|
-
|
1469
|
-
return value;
|
1470
|
-
},
|
1471
|
-
|
1472
|
-
size: function(elm, value) {
|
1473
|
-
value = elm.size;
|
1474
|
-
|
1475
|
-
if (value === 20) {
|
1476
|
-
return undef;
|
1477
|
-
}
|
1478
|
-
|
1479
|
-
return value;
|
1480
|
-
},
|
1481
|
-
|
1482
|
-
'class': function(elm) {
|
1483
|
-
return elm.className;
|
1484
|
-
},
|
1485
|
-
|
1486
|
-
style: function(elm) {
|
1487
|
-
if (elm.style.cssText.length === 0) {
|
1488
|
-
return undef;
|
1489
|
-
}
|
1490
|
-
|
1491
|
-
return elm.style.cssText;
|
1492
|
-
}
|
1493
|
-
});
|
1494
|
-
|
1495
|
-
appendHooks(attrSetHooks, {
|
1496
|
-
'class': function(elm, value) {
|
1497
|
-
elm.className = value;
|
1498
|
-
},
|
1499
|
-
|
1500
|
-
style: function(elm, value) {
|
1501
|
-
elm.style.cssText = value;
|
1502
|
-
}
|
1503
|
-
});
|
1504
|
-
}
|
1456
|
+
var attrHooks = {}, cssHooks = {};
|
1505
1457
|
|
1506
1458
|
function DomQuery(selector, context) {
|
1507
1459
|
/*eslint new-cap:0 */
|
@@ -1561,6 +1513,30 @@ define("tinymce/dom/DomQuery", [
|
|
1561
1513
|
return obj;
|
1562
1514
|
}
|
1563
1515
|
|
1516
|
+
function grep(array, callback) {
|
1517
|
+
var out = [];
|
1518
|
+
|
1519
|
+
each(array, function(i, item) {
|
1520
|
+
if (callback(item, i)) {
|
1521
|
+
out.push(item);
|
1522
|
+
}
|
1523
|
+
});
|
1524
|
+
|
1525
|
+
return out;
|
1526
|
+
}
|
1527
|
+
|
1528
|
+
function getElementDocument(element) {
|
1529
|
+
if (!element) {
|
1530
|
+
return doc;
|
1531
|
+
}
|
1532
|
+
|
1533
|
+
if (element.nodeType == 9) {
|
1534
|
+
return element;
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
return element.ownerDocument;
|
1538
|
+
}
|
1539
|
+
|
1564
1540
|
DomQuery.fn = DomQuery.prototype = {
|
1565
1541
|
constructor: DomQuery,
|
1566
1542
|
|
@@ -1631,14 +1607,18 @@ define("tinymce/dom/DomQuery", [
|
|
1631
1607
|
|
1632
1608
|
if (match) {
|
1633
1609
|
if (match[1]) {
|
1634
|
-
node = createFragment(selector, context).firstChild;
|
1610
|
+
node = createFragment(selector, getElementDocument(context)).firstChild;
|
1635
1611
|
|
1636
1612
|
while (node) {
|
1637
1613
|
push.call(self, node);
|
1638
1614
|
node = node.nextSibling;
|
1639
1615
|
}
|
1640
1616
|
} else {
|
1641
|
-
node =
|
1617
|
+
node = getElementDocument(context).getElementById(match[2]);
|
1618
|
+
|
1619
|
+
if (!node) {
|
1620
|
+
return self;
|
1621
|
+
}
|
1642
1622
|
|
1643
1623
|
if (node.id !== match[2]) {
|
1644
1624
|
return self.find(selector);
|
@@ -1718,9 +1698,10 @@ define("tinymce/dom/DomQuery", [
|
|
1718
1698
|
var hook;
|
1719
1699
|
|
1720
1700
|
if (this.nodeType === 1) {
|
1721
|
-
hook =
|
1722
|
-
if (hook) {
|
1723
|
-
hook(this, value
|
1701
|
+
hook = attrHooks[name];
|
1702
|
+
if (hook && hook.set) {
|
1703
|
+
hook.set(this, value);
|
1704
|
+
return;
|
1724
1705
|
}
|
1725
1706
|
|
1726
1707
|
if (value === null) {
|
@@ -1732,17 +1713,17 @@ define("tinymce/dom/DomQuery", [
|
|
1732
1713
|
});
|
1733
1714
|
} else {
|
1734
1715
|
if (self[0] && self[0].nodeType === 1) {
|
1716
|
+
hook = attrHooks[name];
|
1717
|
+
if (hook && hook.get) {
|
1718
|
+
return hook.get(self[0], name);
|
1719
|
+
}
|
1720
|
+
|
1735
1721
|
if (booleanMap[name]) {
|
1736
1722
|
return self.prop(name) ? name : undef;
|
1737
1723
|
}
|
1738
1724
|
|
1739
1725
|
value = self[0].getAttribute(name, 2);
|
1740
1726
|
|
1741
|
-
hook = attrGetHooks[name];
|
1742
|
-
if (hook) {
|
1743
|
-
return hook(self[0], value, name);
|
1744
|
-
}
|
1745
|
-
|
1746
1727
|
if (value === null) {
|
1747
1728
|
value = undef;
|
1748
1729
|
}
|
@@ -1808,19 +1789,28 @@ define("tinymce/dom/DomQuery", [
|
|
1808
1789
|
* @return {tinymce.dom.DomQuery/String} Current set or the specified style when only the name is specified.
|
1809
1790
|
*/
|
1810
1791
|
css: function(name, value) {
|
1811
|
-
var self = this;
|
1792
|
+
var self = this, elm, hook;
|
1793
|
+
|
1794
|
+
function camel(name) {
|
1795
|
+
return name.replace(/-(\D)/g, function(a, b) {
|
1796
|
+
return b.toUpperCase();
|
1797
|
+
});
|
1798
|
+
}
|
1799
|
+
|
1800
|
+
function dashed(name) {
|
1801
|
+
return name.replace(/[A-Z]/g, function(a) {
|
1802
|
+
return '-' + a;
|
1803
|
+
});
|
1804
|
+
}
|
1812
1805
|
|
1813
1806
|
if (typeof name === "object") {
|
1814
1807
|
each(name, function(name, value) {
|
1815
1808
|
self.css(name, value);
|
1816
1809
|
});
|
1817
1810
|
} else {
|
1818
|
-
// Camelcase it, if needed
|
1819
|
-
name = name.replace(/-(\D)/g, function(a, b) {
|
1820
|
-
return b.toUpperCase();
|
1821
|
-
});
|
1822
|
-
|
1823
1811
|
if (isDefined(value)) {
|
1812
|
+
name = camel(name);
|
1813
|
+
|
1824
1814
|
// Default px suffix on these
|
1825
1815
|
if (typeof(value) === 'number' && !numericCssMap[name]) {
|
1826
1816
|
value += 'px';
|
@@ -1829,31 +1819,42 @@ define("tinymce/dom/DomQuery", [
|
|
1829
1819
|
self.each(function() {
|
1830
1820
|
var style = this.style;
|
1831
1821
|
|
1832
|
-
|
1833
|
-
if (
|
1834
|
-
|
1822
|
+
hook = cssHooks[name];
|
1823
|
+
if (hook && hook.set) {
|
1824
|
+
hook.set(this, value);
|
1825
|
+
return;
|
1835
1826
|
}
|
1836
1827
|
|
1837
1828
|
try {
|
1838
|
-
style[name] = value;
|
1829
|
+
this.style[cssFix[name] || name] = value;
|
1839
1830
|
} catch (ex) {
|
1840
1831
|
// Ignore
|
1841
1832
|
}
|
1833
|
+
|
1834
|
+
if (value === null || value === '') {
|
1835
|
+
if (style.removeProperty) {
|
1836
|
+
style.removeProperty(dashed(name));
|
1837
|
+
} else {
|
1838
|
+
style.removeAttribute(name);
|
1839
|
+
}
|
1840
|
+
}
|
1842
1841
|
});
|
1843
1842
|
} else {
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1843
|
+
elm = self[0];
|
1844
|
+
|
1845
|
+
hook = cssHooks[name];
|
1846
|
+
if (hook && hook.get) {
|
1847
|
+
return hook.get(elm);
|
1848
|
+
}
|
1849
1849
|
|
1850
|
+
if (elm.ownerDocument.defaultView) {
|
1850
1851
|
try {
|
1851
|
-
return
|
1852
|
+
return elm.ownerDocument.defaultView.getComputedStyle(elm, null).getPropertyValue(dashed(name));
|
1852
1853
|
} catch (ex) {
|
1853
1854
|
return undef;
|
1854
1855
|
}
|
1855
|
-
} else if (
|
1856
|
-
return
|
1856
|
+
} else if (elm.currentStyle) {
|
1857
|
+
return elm.currentStyle[camel(name)];
|
1857
1858
|
}
|
1858
1859
|
}
|
1859
1860
|
}
|
@@ -2105,10 +2106,8 @@ define("tinymce/dom/DomQuery", [
|
|
2105
2106
|
* @return {tinymce.dom.DomQuery} Set with unwrapped nodes.
|
2106
2107
|
*/
|
2107
2108
|
unwrap: function() {
|
2108
|
-
return this.each(function() {
|
2109
|
-
|
2110
|
-
parentNode.before(parentNode.contents());
|
2111
|
-
parentNode.remove();
|
2109
|
+
return this.parent().each(function() {
|
2110
|
+
DomQuery(this).replaceWith(this.childNodes);
|
2112
2111
|
});
|
2113
2112
|
},
|
2114
2113
|
|
@@ -2342,10 +2341,16 @@ define("tinymce/dom/DomQuery", [
|
|
2342
2341
|
* Filters the current set with the specified selector.
|
2343
2342
|
*
|
2344
2343
|
* @method filter
|
2345
|
-
* @param {String} selector Selector to filter elements by.
|
2344
|
+
* @param {String/function} selector Selector to filter elements by.
|
2346
2345
|
* @return {tinymce.dom.DomQuery} Set with filtered elements.
|
2347
2346
|
*/
|
2348
2347
|
filter: function(selector) {
|
2348
|
+
if (typeof selector == 'function') {
|
2349
|
+
return DomQuery(grep(this.toArray(), function(item, i) {
|
2350
|
+
return selector(i, item);
|
2351
|
+
}));
|
2352
|
+
}
|
2353
|
+
|
2349
2354
|
return DomQuery(DomQuery.filter(selector, this.toArray()));
|
2350
2355
|
},
|
2351
2356
|
|
@@ -2353,15 +2358,22 @@ define("tinymce/dom/DomQuery", [
|
|
2353
2358
|
* Gets the current node or any partent matching the specified selector.
|
2354
2359
|
*
|
2355
2360
|
* @method closest
|
2356
|
-
* @param {String} selector Selector
|
2361
|
+
* @param {String/Element/tinymce.dom.DomQuery} selector Selector or element to find.
|
2357
2362
|
* @return {tinymce.dom.DomQuery} Set with closest elements.
|
2358
2363
|
*/
|
2359
2364
|
closest: function(selector) {
|
2360
2365
|
var result = [];
|
2361
2366
|
|
2367
|
+
if (selector instanceof DomQuery) {
|
2368
|
+
selector = selector[0];
|
2369
|
+
}
|
2370
|
+
|
2362
2371
|
this.each(function(i, node) {
|
2363
2372
|
while (node) {
|
2364
|
-
if (selector
|
2373
|
+
if (typeof selector == 'string' && DomQuery(node).is(selector)) {
|
2374
|
+
result.push(node);
|
2375
|
+
break;
|
2376
|
+
} else if (node == selector) {
|
2365
2377
|
result.push(node);
|
2366
2378
|
break;
|
2367
2379
|
}
|
@@ -2373,6 +2385,40 @@ define("tinymce/dom/DomQuery", [
|
|
2373
2385
|
return DomQuery(result);
|
2374
2386
|
},
|
2375
2387
|
|
2388
|
+
/**
|
2389
|
+
* Returns the offset of the first element in set or sets the top/left css properties of all elements in set.
|
2390
|
+
*
|
2391
|
+
* @method offset
|
2392
|
+
* @param {Object} offset Optional offset object to set on each item.
|
2393
|
+
* @return {Object/tinymce.dom.DomQuery} Returns the first element offset or the current set if you specified an offset.
|
2394
|
+
*/
|
2395
|
+
offset: function(offset) {
|
2396
|
+
var elm, doc, docElm;
|
2397
|
+
var x = 0, y = 0, pos;
|
2398
|
+
|
2399
|
+
if (!offset) {
|
2400
|
+
elm = this[0];
|
2401
|
+
|
2402
|
+
if (elm) {
|
2403
|
+
doc = elm.ownerDocument;
|
2404
|
+
docElm = doc.documentElement;
|
2405
|
+
|
2406
|
+
if (elm.getBoundingClientRect) {
|
2407
|
+
pos = elm.getBoundingClientRect();
|
2408
|
+
x = pos.left + (docElm.scrollLeft || doc.body.scrollLeft) - docElm.clientLeft;
|
2409
|
+
y = pos.top + (docElm.scrollTop || doc.body.scrollTop) - docElm.clientTop;
|
2410
|
+
}
|
2411
|
+
}
|
2412
|
+
|
2413
|
+
return {
|
2414
|
+
left: x,
|
2415
|
+
top: y
|
2416
|
+
};
|
2417
|
+
}
|
2418
|
+
|
2419
|
+
return this.css(offset);
|
2420
|
+
},
|
2421
|
+
|
2376
2422
|
push: push,
|
2377
2423
|
sort: [].sort,
|
2378
2424
|
splice: [].splice
|
@@ -2443,6 +2489,21 @@ define("tinymce/dom/DomQuery", [
|
|
2443
2489
|
*/
|
2444
2490
|
trim: trim,
|
2445
2491
|
|
2492
|
+
/**
|
2493
|
+
* Filters out items from the input array by calling the specified function for each item.
|
2494
|
+
* If the function returns false the item will be excluded if it returns true it will be included.
|
2495
|
+
*
|
2496
|
+
* @static
|
2497
|
+
* @method grep
|
2498
|
+
* @param {Array} array Array of items to loop though.
|
2499
|
+
* @param {function} callback Function to call for each item. Include/exclude depends on it's return value.
|
2500
|
+
* @return {Array} New array with values imported and filtered based in input.
|
2501
|
+
* @example
|
2502
|
+
* // Filter out some items, this will return an array with 4 and 5
|
2503
|
+
* var items = DomQuery.grep([1, 2, 3, 4, 5], function(v) {return v > 3;});
|
2504
|
+
*/
|
2505
|
+
grep: grep,
|
2506
|
+
|
2446
2507
|
// Sizzle
|
2447
2508
|
find: Sizzle,
|
2448
2509
|
expr: Sizzle.selectors,
|
@@ -2467,7 +2528,21 @@ define("tinymce/dom/DomQuery", [
|
|
2467
2528
|
function dir(el, prop, until) {
|
2468
2529
|
var matched = [], cur = el[prop];
|
2469
2530
|
|
2470
|
-
|
2531
|
+
if (typeof until != 'string' && until instanceof DomQuery) {
|
2532
|
+
until = until[0];
|
2533
|
+
}
|
2534
|
+
|
2535
|
+
while (cur && cur.nodeType !== 9) {
|
2536
|
+
if (until !== undefined) {
|
2537
|
+
if (cur === until) {
|
2538
|
+
break;
|
2539
|
+
}
|
2540
|
+
|
2541
|
+
if (typeof until == 'string' && DomQuery(cur).is(until)) {
|
2542
|
+
break;
|
2543
|
+
}
|
2544
|
+
}
|
2545
|
+
|
2471
2546
|
if (cur.nodeType === 1) {
|
2472
2547
|
matched.push(cur);
|
2473
2548
|
}
|
@@ -2481,13 +2556,23 @@ define("tinymce/dom/DomQuery", [
|
|
2481
2556
|
function sibling(node, siblingName, nodeType, until) {
|
2482
2557
|
var result = [];
|
2483
2558
|
|
2559
|
+
if (until instanceof DomQuery) {
|
2560
|
+
until = until[0];
|
2561
|
+
}
|
2562
|
+
|
2484
2563
|
for (; node; node = node[siblingName]) {
|
2485
2564
|
if (nodeType && node.nodeType !== nodeType) {
|
2486
2565
|
continue;
|
2487
2566
|
}
|
2488
2567
|
|
2489
|
-
if (until
|
2490
|
-
|
2568
|
+
if (until !== undefined) {
|
2569
|
+
if (node === until) {
|
2570
|
+
break;
|
2571
|
+
}
|
2572
|
+
|
2573
|
+
if (typeof until == 'string' && DomQuery(node).is(until)) {
|
2574
|
+
break;
|
2575
|
+
}
|
2491
2576
|
}
|
2492
2577
|
|
2493
2578
|
result.push(node);
|
@@ -2531,18 +2616,6 @@ define("tinymce/dom/DomQuery", [
|
|
2531
2616
|
return dir(node, "parentNode");
|
2532
2617
|
},
|
2533
2618
|
|
2534
|
-
/**
|
2535
|
-
* Returns a new collection with the all the parents until the matching selector/element
|
2536
|
-
* of each item in current collection matching the optional selector.
|
2537
|
-
*
|
2538
|
-
* @method parentsUntil
|
2539
|
-
* @param {String/Element} until Until the matching selector or element.
|
2540
|
-
* @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
|
2541
|
-
*/
|
2542
|
-
parentsUntil: function(node, until) {
|
2543
|
-
return dir(node, "parentNode", until);
|
2544
|
-
},
|
2545
|
-
|
2546
2619
|
/**
|
2547
2620
|
* Returns a new collection with next sibling of each item in current collection matching the optional selector.
|
2548
2621
|
*
|
@@ -2566,49 +2639,96 @@ define("tinymce/dom/DomQuery", [
|
|
2566
2639
|
},
|
2567
2640
|
|
2568
2641
|
/**
|
2569
|
-
* Returns
|
2642
|
+
* Returns all child elements matching the optional selector.
|
2570
2643
|
*
|
2571
|
-
* @method
|
2572
|
-
* @param {String
|
2644
|
+
* @method children
|
2645
|
+
* @param {String} selector Selector to match the elements against.
|
2573
2646
|
* @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
|
2574
2647
|
*/
|
2575
|
-
|
2576
|
-
return sibling(node, 'nextSibling', 1
|
2648
|
+
children: function(node) {
|
2649
|
+
return sibling(node.firstChild, 'nextSibling', 1);
|
2577
2650
|
},
|
2578
2651
|
|
2579
2652
|
/**
|
2580
|
-
* Returns
|
2653
|
+
* Returns all child nodes matching the optional selector.
|
2581
2654
|
*
|
2582
|
-
* @method
|
2583
|
-
* @param {String/Element} until Until the matching selector or element.
|
2655
|
+
* @method contents
|
2584
2656
|
* @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
|
2585
2657
|
*/
|
2586
|
-
|
2587
|
-
return
|
2658
|
+
contents: function(node) {
|
2659
|
+
return Tools.toArray((node.nodeName === "iframe" ? node.contentDocument || node.contentWindow.document : node).childNodes);
|
2660
|
+
}
|
2661
|
+
}, function(name, fn) {
|
2662
|
+
DomQuery.fn[name] = function(selector) {
|
2663
|
+
var self = this, result = [];
|
2664
|
+
|
2665
|
+
self.each(function() {
|
2666
|
+
var nodes = fn.call(result, this, selector, result);
|
2667
|
+
|
2668
|
+
if (nodes) {
|
2669
|
+
if (DomQuery.isArray(nodes)) {
|
2670
|
+
result.push.apply(result, nodes);
|
2671
|
+
} else {
|
2672
|
+
result.push(nodes);
|
2673
|
+
}
|
2674
|
+
}
|
2675
|
+
});
|
2676
|
+
|
2677
|
+
// If traversing on multiple elements we might get the same elements twice
|
2678
|
+
if (this.length > 1) {
|
2679
|
+
result = DomQuery.unique(result);
|
2680
|
+
|
2681
|
+
if (name.indexOf('parents') === 0) {
|
2682
|
+
result = result.reverse();
|
2683
|
+
}
|
2684
|
+
}
|
2685
|
+
|
2686
|
+
result = DomQuery(result);
|
2687
|
+
|
2688
|
+
if (selector) {
|
2689
|
+
return result.filter(selector);
|
2690
|
+
}
|
2691
|
+
|
2692
|
+
return result;
|
2693
|
+
};
|
2694
|
+
});
|
2695
|
+
|
2696
|
+
each({
|
2697
|
+
/**
|
2698
|
+
* Returns a new collection with the all the parents until the matching selector/element
|
2699
|
+
* of each item in current collection matching the optional selector.
|
2700
|
+
*
|
2701
|
+
* @method parentsUntil
|
2702
|
+
* @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
|
2703
|
+
* @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
|
2704
|
+
*/
|
2705
|
+
parentsUntil: function(node, until) {
|
2706
|
+
return dir(node, "parentNode", until);
|
2588
2707
|
},
|
2589
2708
|
|
2590
2709
|
/**
|
2591
|
-
* Returns all
|
2710
|
+
* Returns a new collection with all next siblings of each item in current collection matching the optional selector.
|
2592
2711
|
*
|
2593
|
-
* @method
|
2594
|
-
* @param {String}
|
2712
|
+
* @method nextUntil
|
2713
|
+
* @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
|
2595
2714
|
* @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
|
2596
2715
|
*/
|
2597
|
-
|
2598
|
-
return sibling(node
|
2716
|
+
nextUntil: function(node, until) {
|
2717
|
+
return sibling(node, 'nextSibling', 1, until).slice(1);
|
2599
2718
|
},
|
2600
2719
|
|
2601
2720
|
/**
|
2602
|
-
* Returns all
|
2721
|
+
* Returns a new collection with all previous siblings of each item in current collection matching the optional selector.
|
2603
2722
|
*
|
2604
|
-
* @method
|
2723
|
+
* @method prevUntil
|
2724
|
+
* @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
|
2605
2725
|
* @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
|
2606
2726
|
*/
|
2607
|
-
|
2608
|
-
return
|
2727
|
+
prevUntil: function(node, until) {
|
2728
|
+
return sibling(node, 'previousSibling', 1, until).slice(1);
|
2609
2729
|
}
|
2610
2730
|
}, function(name, fn) {
|
2611
|
-
DomQuery.fn[name] = function(selector) {
|
2731
|
+
DomQuery.fn[name] = function(selector, filter) {
|
2612
2732
|
var self = this, result = [];
|
2613
2733
|
|
2614
2734
|
self.each(function() {
|
@@ -2623,16 +2743,19 @@ define("tinymce/dom/DomQuery", [
|
|
2623
2743
|
}
|
2624
2744
|
});
|
2625
2745
|
|
2626
|
-
|
2746
|
+
// If traversing on multiple elements we might get the same elements twice
|
2747
|
+
if (this.length > 1) {
|
2748
|
+
result = DomQuery.unique(result);
|
2627
2749
|
|
2628
|
-
|
2629
|
-
|
2750
|
+
if (name.indexOf('parents') === 0 || name === 'prevUntil') {
|
2751
|
+
result = result.reverse();
|
2752
|
+
}
|
2630
2753
|
}
|
2631
2754
|
|
2632
2755
|
result = DomQuery(result);
|
2633
2756
|
|
2634
|
-
if (
|
2635
|
-
return result.filter(
|
2757
|
+
if (filter) {
|
2758
|
+
return result.filter(filter);
|
2636
2759
|
}
|
2637
2760
|
|
2638
2761
|
return result;
|
@@ -2657,7 +2780,16 @@ define("tinymce/dom/DomQuery", [
|
|
2657
2780
|
|
2658
2781
|
function jQuerySub(selector, context) {
|
2659
2782
|
defaults = defaults || callback();
|
2660
|
-
|
2783
|
+
|
2784
|
+
if (arguments.length === 0) {
|
2785
|
+
selector = defaults.element;
|
2786
|
+
}
|
2787
|
+
|
2788
|
+
if (!context) {
|
2789
|
+
context = defaults.context;
|
2790
|
+
}
|
2791
|
+
|
2792
|
+
return new jQuerySub.fn.init(selector, context);
|
2661
2793
|
}
|
2662
2794
|
|
2663
2795
|
DomQuery.extend(jQuerySub, this);
|
@@ -2665,38 +2797,113 @@ define("tinymce/dom/DomQuery", [
|
|
2665
2797
|
return jQuerySub;
|
2666
2798
|
};
|
2667
2799
|
|
2668
|
-
|
2669
|
-
|
2800
|
+
function appendHooks(targetHooks, prop, hooks) {
|
2801
|
+
each(hooks, function(name, func) {
|
2802
|
+
targetHooks[name] = targetHooks[name] || {};
|
2803
|
+
targetHooks[name][prop] = func;
|
2804
|
+
});
|
2805
|
+
}
|
2670
2806
|
|
2671
|
-
|
2807
|
+
if (Env.ie && Env.ie < 8) {
|
2808
|
+
appendHooks(attrHooks, 'get', {
|
2809
|
+
maxlength: function(elm) {
|
2810
|
+
var value = elm.maxLength;
|
2672
2811
|
|
2673
|
-
|
2674
|
-
|
2675
|
-
|
2676
|
-
* Copyright, Moxiecode Systems AB
|
2677
|
-
* Released under LGPL License.
|
2678
|
-
*
|
2679
|
-
* License: http://www.tinymce.com/license
|
2680
|
-
* Contributing: http://www.tinymce.com/contributing
|
2681
|
-
*/
|
2812
|
+
if (value === 0x7fffffff) {
|
2813
|
+
return undef;
|
2814
|
+
}
|
2682
2815
|
|
2683
|
-
|
2684
|
-
|
2685
|
-
|
2686
|
-
|
2687
|
-
|
2688
|
-
|
2689
|
-
|
2690
|
-
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2816
|
+
return value;
|
2817
|
+
},
|
2818
|
+
|
2819
|
+
size: function(elm) {
|
2820
|
+
var value = elm.size;
|
2821
|
+
|
2822
|
+
if (value === 20) {
|
2823
|
+
return undef;
|
2824
|
+
}
|
2825
|
+
|
2826
|
+
return value;
|
2827
|
+
},
|
2828
|
+
|
2829
|
+
'class': function(elm) {
|
2830
|
+
return elm.className;
|
2831
|
+
},
|
2832
|
+
|
2833
|
+
style: function(elm) {
|
2834
|
+
var value = elm.style.cssText;
|
2835
|
+
|
2836
|
+
if (value.length === 0) {
|
2837
|
+
return undef;
|
2838
|
+
}
|
2839
|
+
|
2840
|
+
return value;
|
2841
|
+
}
|
2842
|
+
});
|
2843
|
+
|
2844
|
+
appendHooks(attrHooks, 'set', {
|
2845
|
+
'class': function(elm, value) {
|
2846
|
+
elm.className = value;
|
2847
|
+
},
|
2848
|
+
|
2849
|
+
style: function(elm, value) {
|
2850
|
+
elm.style.cssText = value;
|
2851
|
+
}
|
2852
|
+
});
|
2853
|
+
}
|
2854
|
+
|
2855
|
+
if (Env.ie && Env.ie < 9) {
|
2856
|
+
cssFix.float = 'styleFloat';
|
2857
|
+
|
2858
|
+
appendHooks(cssHooks, 'set', {
|
2859
|
+
opacity: function(elm, value) {
|
2860
|
+
var style = elm.style;
|
2861
|
+
|
2862
|
+
if (value === null || value === '') {
|
2863
|
+
style.removeAttribute('filter');
|
2864
|
+
} else {
|
2865
|
+
style.zoom = 1;
|
2866
|
+
style.filter = 'alpha(opacity=' + (value * 100) + ')';
|
2867
|
+
}
|
2868
|
+
}
|
2869
|
+
});
|
2870
|
+
}
|
2871
|
+
|
2872
|
+
DomQuery.attrHooks = attrHooks;
|
2873
|
+
DomQuery.cssHooks = cssHooks;
|
2874
|
+
|
2875
|
+
return DomQuery;
|
2876
|
+
});
|
2877
|
+
|
2878
|
+
// Included from: js/tinymce/classes/html/Styles.js
|
2879
|
+
|
2880
|
+
/**
|
2881
|
+
* Styles.js
|
2882
|
+
*
|
2883
|
+
* Copyright, Moxiecode Systems AB
|
2884
|
+
* Released under LGPL License.
|
2885
|
+
*
|
2886
|
+
* License: http://www.tinymce.com/license
|
2887
|
+
* Contributing: http://www.tinymce.com/contributing
|
2888
|
+
*/
|
2889
|
+
|
2890
|
+
/**
|
2891
|
+
* This class is used to parse CSS styles it also compresses styles to reduce the output size.
|
2892
|
+
*
|
2893
|
+
* @example
|
2894
|
+
* var Styles = new tinymce.html.Styles({
|
2895
|
+
* url_converter: function(url) {
|
2896
|
+
* return url;
|
2897
|
+
* }
|
2898
|
+
* });
|
2899
|
+
*
|
2900
|
+
* styles = Styles.parse('border: 1px solid red');
|
2901
|
+
* styles.color = 'red';
|
2902
|
+
*
|
2903
|
+
* console.log(new tinymce.html.StyleSerializer().serialize(styles));
|
2904
|
+
*
|
2905
|
+
* @class tinymce.html.Styles
|
2906
|
+
* @version 3.4
|
2700
2907
|
*/
|
2701
2908
|
define("tinymce/html/Styles", [], function() {
|
2702
2909
|
return function(settings, schema) {
|
@@ -3050,30 +3257,44 @@ define("tinymce/html/Styles", [], function() {
|
|
3050
3257
|
* TreeWalker class enables you to walk the DOM in a linear manner.
|
3051
3258
|
*
|
3052
3259
|
* @class tinymce.dom.TreeWalker
|
3260
|
+
* @example
|
3261
|
+
* var walker = new tinymce.dom.TreeWalker(startNode);
|
3262
|
+
*
|
3263
|
+
* do {
|
3264
|
+
* console.log(walker.current());
|
3265
|
+
* } while (walker.next());
|
3053
3266
|
*/
|
3054
3267
|
define("tinymce/dom/TreeWalker", [], function() {
|
3055
|
-
|
3056
|
-
|
3268
|
+
/**
|
3269
|
+
* Constructs a new TreeWalker instance.
|
3270
|
+
*
|
3271
|
+
* @constructor
|
3272
|
+
* @method TreeWalker
|
3273
|
+
* @param {Node} startNode Node to start walking from.
|
3274
|
+
* @param {node} rootNode Optional root node to never walk out of.
|
3275
|
+
*/
|
3276
|
+
return function(startNode, rootNode) {
|
3277
|
+
var node = startNode;
|
3057
3278
|
|
3058
|
-
function findSibling(node,
|
3279
|
+
function findSibling(node, startName, siblingName, shallow) {
|
3059
3280
|
var sibling, parent;
|
3060
3281
|
|
3061
3282
|
if (node) {
|
3062
3283
|
// Walk into nodes if it has a start
|
3063
|
-
if (!shallow && node[
|
3064
|
-
return node[
|
3284
|
+
if (!shallow && node[startName]) {
|
3285
|
+
return node[startName];
|
3065
3286
|
}
|
3066
3287
|
|
3067
3288
|
// Return the sibling if it has one
|
3068
|
-
if (node !=
|
3069
|
-
sibling = node[
|
3289
|
+
if (node != rootNode) {
|
3290
|
+
sibling = node[siblingName];
|
3070
3291
|
if (sibling) {
|
3071
3292
|
return sibling;
|
3072
3293
|
}
|
3073
3294
|
|
3074
3295
|
// Walk up the parents to look for siblings
|
3075
|
-
for (parent = node.parentNode; parent && parent !=
|
3076
|
-
sibling = parent[
|
3296
|
+
for (parent = node.parentNode; parent && parent != rootNode; parent = parent.parentNode) {
|
3297
|
+
sibling = parent[siblingName];
|
3077
3298
|
if (sibling) {
|
3078
3299
|
return sibling;
|
3079
3300
|
}
|
@@ -4385,13 +4606,61 @@ define("tinymce/dom/DOMUtils", [
|
|
4385
4606
|
"tinymce/Env",
|
4386
4607
|
"tinymce/util/Tools",
|
4387
4608
|
"tinymce/dom/StyleSheetLoader"
|
4388
|
-
], function(Sizzle,
|
4609
|
+
], function(Sizzle, $, Styles, EventUtils, TreeWalker, Range, Entities, Env, Tools, StyleSheetLoader) {
|
4389
4610
|
// Shorten names
|
4390
|
-
var each = Tools.each, is = Tools.is, grep = Tools.grep, trim = Tools.trim
|
4391
|
-
var
|
4611
|
+
var each = Tools.each, is = Tools.is, grep = Tools.grep, trim = Tools.trim;
|
4612
|
+
var isIE = Env.ie;
|
4392
4613
|
var simpleSelectorRe = /^([a-z0-9],?)+$/i;
|
4393
4614
|
var whiteSpaceRegExp = /^[ \t\r\n]*$/;
|
4394
|
-
|
4615
|
+
|
4616
|
+
function setupAttrHooks(domUtils, settings) {
|
4617
|
+
var attrHooks = {}, keepValues = settings.keep_values, keepUrlHook;
|
4618
|
+
|
4619
|
+
keepUrlHook = {
|
4620
|
+
set: function($elm, value, name) {
|
4621
|
+
if (settings.url_converter) {
|
4622
|
+
value = settings.url_converter.call(settings.url_converter_scope || domUtils, value, name, $elm[0]);
|
4623
|
+
}
|
4624
|
+
|
4625
|
+
$elm.attr('data-mce-' + name, value).attr(name, value);
|
4626
|
+
},
|
4627
|
+
|
4628
|
+
get: function($elm, name) {
|
4629
|
+
return $elm.attr('data-mce-' + name) || $elm.attr(name);
|
4630
|
+
}
|
4631
|
+
};
|
4632
|
+
|
4633
|
+
attrHooks = {
|
4634
|
+
style: {
|
4635
|
+
set: function($elm, value) {
|
4636
|
+
if (value !== null && typeof value === 'object') {
|
4637
|
+
$elm.css(value);
|
4638
|
+
return;
|
4639
|
+
}
|
4640
|
+
|
4641
|
+
if (keepValues) {
|
4642
|
+
$elm.attr('data-mce-style', value);
|
4643
|
+
}
|
4644
|
+
|
4645
|
+
$elm.attr('style', value);
|
4646
|
+
},
|
4647
|
+
|
4648
|
+
get: function($elm) {
|
4649
|
+
var value = $elm.attr('data-mce-style') || $elm.attr('style');
|
4650
|
+
|
4651
|
+
value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);
|
4652
|
+
|
4653
|
+
return value;
|
4654
|
+
}
|
4655
|
+
}
|
4656
|
+
};
|
4657
|
+
|
4658
|
+
if (keepValues) {
|
4659
|
+
attrHooks.href = attrHooks.src = keepUrlHook;
|
4660
|
+
}
|
4661
|
+
|
4662
|
+
return attrHooks;
|
4663
|
+
}
|
4395
4664
|
|
4396
4665
|
/**
|
4397
4666
|
* Constructs a new DOMUtils instance. Consult the Wiki for more details on settings etc for this class.
|
@@ -4410,15 +4679,9 @@ define("tinymce/dom/DOMUtils", [
|
|
4410
4679
|
self.counter = 0;
|
4411
4680
|
self.stdMode = !isIE || doc.documentMode >= 8;
|
4412
4681
|
self.boxModel = !isIE || doc.compatMode == "CSS1Compat" || self.stdMode;
|
4413
|
-
self.hasOuterHTML = "outerHTML" in doc.createElement("a");
|
4414
4682
|
self.styleSheetLoader = new StyleSheetLoader(doc);
|
4415
|
-
|
4416
|
-
|
4417
|
-
self.settings = settings = extend({
|
4418
|
-
keep_values: false,
|
4419
|
-
hex_colors: 1
|
4420
|
-
}, settings);
|
4421
|
-
|
4683
|
+
self.boundEvents = [];
|
4684
|
+
self.settings = settings = settings || {};
|
4422
4685
|
self.schema = settings.schema;
|
4423
4686
|
self.styles = new Styles({
|
4424
4687
|
url_converter: settings.url_converter,
|
@@ -4427,8 +4690,9 @@ define("tinymce/dom/DOMUtils", [
|
|
4427
4690
|
|
4428
4691
|
self.fixDoc(doc);
|
4429
4692
|
self.events = settings.ownEvents ? new EventUtils(settings.proxy) : EventUtils.Event;
|
4693
|
+
self.attrHooks = setupAttrHooks(self, settings);
|
4430
4694
|
blockElementsMap = settings.schema ? settings.schema.getBlockElements() : {};
|
4431
|
-
self.$ =
|
4695
|
+
self.$ = $.overrideDefaults(function() {
|
4432
4696
|
return {
|
4433
4697
|
context: doc,
|
4434
4698
|
element: self.getRoot()
|
@@ -4461,22 +4725,16 @@ define("tinymce/dom/DOMUtils", [
|
|
4461
4725
|
}
|
4462
4726
|
|
4463
4727
|
DOMUtils.prototype = {
|
4464
|
-
|
4465
|
-
|
4466
|
-
|
4467
|
-
|
4468
|
-
|
4469
|
-
|
4470
|
-
disabled: "disabled",
|
4471
|
-
maxlength: "maxLength",
|
4472
|
-
readonly: "readOnly",
|
4473
|
-
selected: "selected",
|
4474
|
-
value: "value",
|
4475
|
-
id: "id",
|
4476
|
-
name: "name",
|
4477
|
-
type: "type"
|
4728
|
+
$$: function(elm) {
|
4729
|
+
if (typeof elm == 'string') {
|
4730
|
+
elm = this.get(elm);
|
4731
|
+
}
|
4732
|
+
|
4733
|
+
return this.$(elm);
|
4478
4734
|
},
|
4479
4735
|
|
4736
|
+
root: null,
|
4737
|
+
|
4480
4738
|
fixDoc: function(doc) {
|
4481
4739
|
var settings = this.settings, name;
|
4482
4740
|
|
@@ -4518,19 +4776,7 @@ define("tinymce/dom/DOMUtils", [
|
|
4518
4776
|
|
4519
4777
|
return clone;
|
4520
4778
|
}
|
4521
|
-
/*
|
4522
|
-
// Setup HTML5 patched document fragment
|
4523
|
-
if (!self.frag) {
|
4524
|
-
self.frag = doc.createDocumentFragment();
|
4525
|
-
self.fixDoc(self.frag);
|
4526
|
-
}
|
4527
4779
|
|
4528
|
-
// Make a deep copy by adding it to the document fragment then removing it this removed the :section
|
4529
|
-
clone = doc.createElement('div');
|
4530
|
-
self.frag.appendChild(clone);
|
4531
|
-
clone.innerHTML = node.outerHTML;
|
4532
|
-
self.frag.removeChild(clone);
|
4533
|
-
*/
|
4534
4780
|
return clone.firstChild;
|
4535
4781
|
},
|
4536
4782
|
|
@@ -4544,7 +4790,7 @@ define("tinymce/dom/DOMUtils", [
|
|
4544
4790
|
getRoot: function() {
|
4545
4791
|
var self = this;
|
4546
4792
|
|
4547
|
-
return self.
|
4793
|
+
return self.settings.root_element || self.doc.body;
|
4548
4794
|
},
|
4549
4795
|
|
4550
4796
|
/**
|
@@ -4757,8 +5003,8 @@ define("tinymce/dom/DOMUtils", [
|
|
4757
5003
|
select: function(selector, scope) {
|
4758
5004
|
var self = this;
|
4759
5005
|
|
4760
|
-
|
4761
|
-
return Sizzle(selector, self.get(scope) || self.
|
5006
|
+
/*eslint new-cap:0 */
|
5007
|
+
return Sizzle(selector, self.get(scope) || self.settings.root_element || self.doc, []);
|
4762
5008
|
},
|
4763
5009
|
|
4764
5010
|
/**
|
@@ -4799,6 +5045,8 @@ define("tinymce/dom/DOMUtils", [
|
|
4799
5045
|
}
|
4800
5046
|
|
4801
5047
|
var elms = elm.nodeType ? [elm] : elm;
|
5048
|
+
|
5049
|
+
/*eslint new-cap:0 */
|
4802
5050
|
return Sizzle(selector, elms[0].ownerDocument || elms[0], null, elms).length > 0;
|
4803
5051
|
},
|
4804
5052
|
|
@@ -4916,7 +5164,7 @@ define("tinymce/dom/DOMUtils", [
|
|
4916
5164
|
*
|
4917
5165
|
* @method remove
|
4918
5166
|
* @param {String/Element/Array} node ID of element or DOM element object or array containing multiple elements/ids.
|
4919
|
-
* @param {Boolean}
|
5167
|
+
* @param {Boolean} keepChildren Optional state to keep children or not. If set to true all children will be
|
4920
5168
|
* placed at the location of the removed element.
|
4921
5169
|
* @return {Element/Array} HTML DOM element that got removed, or an array of removed elements if multiple input elements
|
4922
5170
|
* were passed in.
|
@@ -4927,27 +5175,26 @@ define("tinymce/dom/DOMUtils", [
|
|
4927
5175
|
* // Removes an element by id in the document
|
4928
5176
|
* tinymce.DOM.remove('mydiv');
|
4929
5177
|
*/
|
4930
|
-
remove: function(node,
|
4931
|
-
|
4932
|
-
var child, parent = node.parentNode;
|
5178
|
+
remove: function(node, keepChildren) {
|
5179
|
+
node = this.$$(node);
|
4933
5180
|
|
4934
|
-
|
4935
|
-
|
4936
|
-
|
5181
|
+
if (keepChildren) {
|
5182
|
+
node.each(function() {
|
5183
|
+
var child;
|
4937
5184
|
|
4938
|
-
|
4939
|
-
|
4940
|
-
|
4941
|
-
if (!isIE || child.nodeType !== 3 || child.nodeValue) {
|
4942
|
-
parent.insertBefore(child, node);
|
5185
|
+
while ((child = this.firstChild)) {
|
5186
|
+
if (child.nodeType == 3 && child.data.length === 0) {
|
5187
|
+
this.removeChild(child);
|
4943
5188
|
} else {
|
4944
|
-
|
5189
|
+
this.parentNode.insertBefore(child, this);
|
4945
5190
|
}
|
4946
5191
|
}
|
4947
|
-
}
|
5192
|
+
}).remove();
|
5193
|
+
} else {
|
5194
|
+
node.remove();
|
5195
|
+
}
|
4948
5196
|
|
4949
|
-
|
4950
|
-
});
|
5197
|
+
return node.length > 1 ? node.toArray() : node[0];
|
4951
5198
|
},
|
4952
5199
|
|
4953
5200
|
/**
|
@@ -4966,50 +5213,11 @@ define("tinymce/dom/DOMUtils", [
|
|
4966
5213
|
* tinymce.DOM.setStyle('mydiv', 'background-color', 'red');
|
4967
5214
|
*/
|
4968
5215
|
setStyle: function(elm, name, value) {
|
4969
|
-
|
4970
|
-
var self = this, style, key;
|
4971
|
-
|
4972
|
-
if (name) {
|
4973
|
-
if (typeof(name) === 'string') {
|
4974
|
-
style = elm.style;
|
4975
|
-
|
4976
|
-
// Camelcase it, if needed
|
4977
|
-
name = name.replace(/-(\D)/g, function(a, b) {
|
4978
|
-
return b.toUpperCase();
|
4979
|
-
});
|
4980
|
-
|
4981
|
-
// Default px suffix on these
|
4982
|
-
if (((typeof(value) === 'number') || /^[\-0-9\.]+$/.test(value)) && !numericCssMap[name]) {
|
4983
|
-
value += 'px';
|
4984
|
-
}
|
4985
|
-
|
4986
|
-
// IE specific opacity
|
4987
|
-
if (name === "opacity" && elm.runtimeStyle && typeof(elm.runtimeStyle.opacity) === "undefined") {
|
4988
|
-
style.filter = value === '' ? '' : "alpha(opacity=" + (value * 100) + ")";
|
4989
|
-
}
|
4990
|
-
|
4991
|
-
if (name == "float") {
|
4992
|
-
// Old IE vs modern browsers
|
4993
|
-
name = "cssFloat" in elm.style ? "cssFloat" : "styleFloat";
|
4994
|
-
}
|
4995
|
-
|
4996
|
-
try {
|
4997
|
-
style[name] = value;
|
4998
|
-
} catch (ex) {
|
4999
|
-
// Ignore IE errors
|
5000
|
-
}
|
5216
|
+
elm = this.$$(elm).css(name, value);
|
5001
5217
|
|
5002
|
-
|
5003
|
-
|
5004
|
-
|
5005
|
-
}
|
5006
|
-
} else {
|
5007
|
-
for (key in name) {
|
5008
|
-
self.setStyle(elm, key, name[key]);
|
5009
|
-
}
|
5010
|
-
}
|
5011
|
-
}
|
5012
|
-
});
|
5218
|
+
if (this.settings.update_styles) {
|
5219
|
+
elm.attr('data-mce-style', null);
|
5220
|
+
}
|
5013
5221
|
},
|
5014
5222
|
|
5015
5223
|
/**
|
@@ -5022,25 +5230,10 @@ define("tinymce/dom/DOMUtils", [
|
|
5022
5230
|
* @return {String} Current style or computed style value of an element.
|
5023
5231
|
*/
|
5024
5232
|
getStyle: function(elm, name, computed) {
|
5025
|
-
elm = this
|
5026
|
-
|
5027
|
-
if (!elm) {
|
5028
|
-
return;
|
5029
|
-
}
|
5030
|
-
|
5031
|
-
// W3C
|
5032
|
-
if (this.doc.defaultView && computed) {
|
5033
|
-
// Remove camelcase
|
5034
|
-
name = name.replace(/[A-Z]/g, function(a) {
|
5035
|
-
return '-' + a;
|
5036
|
-
});
|
5233
|
+
elm = this.$$(elm);
|
5037
5234
|
|
5038
|
-
|
5039
|
-
|
5040
|
-
} catch (ex) {
|
5041
|
-
// Old safari might fail
|
5042
|
-
return null;
|
5043
|
-
}
|
5235
|
+
if (computed) {
|
5236
|
+
return elm.css(name);
|
5044
5237
|
}
|
5045
5238
|
|
5046
5239
|
// Camelcase it, if needed
|
@@ -5052,12 +5245,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5052
5245
|
name = isIE ? 'styleFloat' : 'cssFloat';
|
5053
5246
|
}
|
5054
5247
|
|
5055
|
-
|
5056
|
-
if (elm.currentStyle && computed) {
|
5057
|
-
return elm.currentStyle[name];
|
5058
|
-
}
|
5059
|
-
|
5060
|
-
return elm.style ? elm.style[name] : undefined;
|
5248
|
+
return elm[0] && elm[0].style ? elm[0].style[name] : undefined;
|
5061
5249
|
},
|
5062
5250
|
|
5063
5251
|
/**
|
@@ -5074,11 +5262,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5074
5262
|
* tinymce.DOM.setStyles('mydiv', {'background-color': 'red', 'color': 'green'});
|
5075
5263
|
*/
|
5076
5264
|
setStyles: function(elm, styles) {
|
5077
|
-
this.
|
5078
|
-
},
|
5079
|
-
|
5080
|
-
css: function(elm, name, value) {
|
5081
|
-
this.setStyle(elm, name, value);
|
5265
|
+
this.$$(elm).css(styles);
|
5082
5266
|
},
|
5083
5267
|
|
5084
5268
|
/**
|
@@ -5111,73 +5295,29 @@ define("tinymce/dom/DOMUtils", [
|
|
5111
5295
|
* tinymce.dom.setAttrib('mydiv', 'class', 'myclass');
|
5112
5296
|
*/
|
5113
5297
|
setAttrib: function(elm, name, value) {
|
5114
|
-
var self = this;
|
5298
|
+
var self = this, originalValue, hook, settings = self.settings;
|
5115
5299
|
|
5116
|
-
|
5117
|
-
|
5118
|
-
return;
|
5300
|
+
if (value === '') {
|
5301
|
+
value = null;
|
5119
5302
|
}
|
5120
5303
|
|
5121
|
-
|
5122
|
-
|
5123
|
-
var originalValue = elm.getAttribute(name);
|
5124
|
-
|
5125
|
-
if (value !== null) {
|
5126
|
-
switch (name) {
|
5127
|
-
case "style":
|
5128
|
-
if (!is(value, 'string')) {
|
5129
|
-
each(value, function(value, name) {
|
5130
|
-
self.setStyle(elm, name, value);
|
5131
|
-
});
|
5132
|
-
|
5133
|
-
return;
|
5134
|
-
}
|
5135
|
-
|
5136
|
-
// No mce_style for elements with these since they might get resized by the user
|
5137
|
-
if (settings.keep_values) {
|
5138
|
-
if (value) {
|
5139
|
-
elm.setAttribute('data-mce-style', value, 2);
|
5140
|
-
} else {
|
5141
|
-
elm.removeAttribute('data-mce-style', 2);
|
5142
|
-
}
|
5143
|
-
}
|
5144
|
-
|
5145
|
-
elm.style.cssText = value;
|
5146
|
-
break;
|
5147
|
-
|
5148
|
-
case "class":
|
5149
|
-
elm.className = value || ''; // Fix IE null bug
|
5150
|
-
break;
|
5151
|
-
|
5152
|
-
case "src":
|
5153
|
-
case "href":
|
5154
|
-
if (settings.keep_values) {
|
5155
|
-
if (settings.url_converter) {
|
5156
|
-
value = settings.url_converter.call(settings.url_converter_scope || self, value, name, elm);
|
5157
|
-
}
|
5158
|
-
|
5159
|
-
self.setAttrib(elm, 'data-mce-' + name, value, 2);
|
5160
|
-
}
|
5161
|
-
|
5162
|
-
break;
|
5163
|
-
|
5164
|
-
case "shape":
|
5165
|
-
elm.setAttribute('data-mce-style', value);
|
5166
|
-
break;
|
5167
|
-
}
|
5168
|
-
}
|
5304
|
+
elm = self.$$(elm);
|
5305
|
+
originalValue = elm.attr(name);
|
5169
5306
|
|
5170
|
-
|
5171
|
-
|
5172
|
-
|
5173
|
-
|
5174
|
-
|
5307
|
+
hook = self.attrHooks[name];
|
5308
|
+
if (hook && hook.set) {
|
5309
|
+
hook.set(elm, value, name);
|
5310
|
+
} else {
|
5311
|
+
elm.attr(name, value);
|
5312
|
+
}
|
5175
5313
|
|
5176
|
-
|
5177
|
-
|
5178
|
-
|
5179
|
-
|
5180
|
-
|
5314
|
+
if (originalValue != value && settings.onSetAttrib) {
|
5315
|
+
settings.onSetAttrib({
|
5316
|
+
attrElm: elm,
|
5317
|
+
attrName: name,
|
5318
|
+
attrValue: value
|
5319
|
+
});
|
5320
|
+
}
|
5181
5321
|
},
|
5182
5322
|
|
5183
5323
|
/**
|
@@ -5196,9 +5336,9 @@ define("tinymce/dom/DOMUtils", [
|
|
5196
5336
|
setAttribs: function(elm, attrs) {
|
5197
5337
|
var self = this;
|
5198
5338
|
|
5199
|
-
|
5339
|
+
self.$$(elm).each(function(i, node) {
|
5200
5340
|
each(attrs, function(value, name) {
|
5201
|
-
self.setAttrib(
|
5341
|
+
self.setAttrib(node, name, value);
|
5202
5342
|
});
|
5203
5343
|
});
|
5204
5344
|
},
|
@@ -5213,186 +5353,69 @@ define("tinymce/dom/DOMUtils", [
|
|
5213
5353
|
* @return {String} Attribute value string, default value or null if the attribute wasn't found.
|
5214
5354
|
*/
|
5215
5355
|
getAttrib: function(elm, name, defaultVal) {
|
5216
|
-
var
|
5356
|
+
var self = this, hook, value;
|
5217
5357
|
|
5218
|
-
elm = self
|
5358
|
+
elm = self.$$(elm);
|
5219
5359
|
|
5220
|
-
|
5221
|
-
|
5360
|
+
hook = self.attrHooks[name];
|
5361
|
+
if (hook && hook.get) {
|
5362
|
+
value = hook.get(elm, name);
|
5363
|
+
} else {
|
5364
|
+
value = elm.attr(name);
|
5222
5365
|
}
|
5223
5366
|
|
5224
|
-
if (
|
5225
|
-
|
5367
|
+
if (typeof value == 'undefined') {
|
5368
|
+
value = defaultVal || '';
|
5226
5369
|
}
|
5227
5370
|
|
5228
|
-
|
5229
|
-
|
5230
|
-
value = elm.getAttribute("data-mce-" + name);
|
5371
|
+
return value;
|
5372
|
+
},
|
5231
5373
|
|
5232
|
-
|
5233
|
-
|
5234
|
-
|
5235
|
-
|
5374
|
+
/**
|
5375
|
+
* Returns the absolute x, y position of a node. The position will be returned in an object with x, y fields.
|
5376
|
+
*
|
5377
|
+
* @method getPos
|
5378
|
+
* @param {Element/String} elm HTML element or element id to get x, y position from.
|
5379
|
+
* @param {Element} rootElm Optional root element to stop calculations at.
|
5380
|
+
* @return {object} Absolute position of the specified element object with x, y fields.
|
5381
|
+
*/
|
5382
|
+
getPos: function(elm, rootElm) {
|
5383
|
+
var self = this, x = 0, y = 0, offsetParent, doc = self.doc, pos;
|
5236
5384
|
|
5237
|
-
|
5238
|
-
|
5239
|
-
value = value && value.nodeValue ? value.nodeValue : value;
|
5240
|
-
}
|
5385
|
+
elm = self.get(elm);
|
5386
|
+
rootElm = rootElm || doc.body;
|
5241
5387
|
|
5242
|
-
if (
|
5243
|
-
|
5244
|
-
|
5388
|
+
if (elm) {
|
5389
|
+
// Use getBoundingClientRect if it exists since it's faster than looping offset nodes
|
5390
|
+
if (rootElm === doc.body && elm.getBoundingClientRect) {
|
5391
|
+
pos = elm.getBoundingClientRect();
|
5392
|
+
rootElm = self.boxModel ? doc.documentElement : doc.body;
|
5245
5393
|
|
5246
|
-
|
5247
|
-
|
5248
|
-
|
5249
|
-
|
5394
|
+
// Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
|
5395
|
+
// Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
|
5396
|
+
x = pos.left + (doc.documentElement.scrollLeft || doc.body.scrollLeft) - rootElm.clientLeft;
|
5397
|
+
y = pos.top + (doc.documentElement.scrollTop || doc.body.scrollTop) - rootElm.clientTop;
|
5398
|
+
|
5399
|
+
return {x: x, y: y};
|
5250
5400
|
}
|
5251
5401
|
|
5252
|
-
|
5253
|
-
|
5402
|
+
offsetParent = elm;
|
5403
|
+
while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
|
5404
|
+
x += offsetParent.offsetLeft || 0;
|
5405
|
+
y += offsetParent.offsetTop || 0;
|
5406
|
+
offsetParent = offsetParent.offsetParent;
|
5407
|
+
}
|
5254
5408
|
|
5255
|
-
|
5256
|
-
|
5257
|
-
|
5409
|
+
offsetParent = elm.parentNode;
|
5410
|
+
while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
|
5411
|
+
x -= offsetParent.scrollLeft || 0;
|
5412
|
+
y -= offsetParent.scrollTop || 0;
|
5413
|
+
offsetParent = offsetParent.parentNode;
|
5414
|
+
}
|
5258
5415
|
}
|
5259
5416
|
|
5260
|
-
|
5261
|
-
|
5262
|
-
|
5263
|
-
if (value) {
|
5264
|
-
value = self.serializeStyle(self.parseStyle(value), elm.nodeName);
|
5265
|
-
|
5266
|
-
if (self.settings.keep_values) {
|
5267
|
-
elm.setAttribute('data-mce-style', value);
|
5268
|
-
}
|
5269
|
-
}
|
5270
|
-
}
|
5271
|
-
|
5272
|
-
// Remove Apple and WebKit stuff
|
5273
|
-
if (isWebKit && name === "class" && value) {
|
5274
|
-
value = value.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
|
5275
|
-
}
|
5276
|
-
|
5277
|
-
// Handle IE issues
|
5278
|
-
if (isIE) {
|
5279
|
-
switch (name) {
|
5280
|
-
case 'rowspan':
|
5281
|
-
case 'colspan':
|
5282
|
-
// IE returns 1 as default value
|
5283
|
-
if (value === 1) {
|
5284
|
-
value = '';
|
5285
|
-
}
|
5286
|
-
|
5287
|
-
break;
|
5288
|
-
|
5289
|
-
case 'size':
|
5290
|
-
// IE returns +0 as default value for size
|
5291
|
-
if (value === '+0' || value === 20 || value === 0) {
|
5292
|
-
value = '';
|
5293
|
-
}
|
5294
|
-
|
5295
|
-
break;
|
5296
|
-
|
5297
|
-
case 'width':
|
5298
|
-
case 'height':
|
5299
|
-
case 'vspace':
|
5300
|
-
case 'checked':
|
5301
|
-
case 'disabled':
|
5302
|
-
case 'readonly':
|
5303
|
-
if (value === 0) {
|
5304
|
-
value = '';
|
5305
|
-
}
|
5306
|
-
|
5307
|
-
break;
|
5308
|
-
|
5309
|
-
case 'hspace':
|
5310
|
-
// IE returns -1 as default value
|
5311
|
-
if (value === -1) {
|
5312
|
-
value = '';
|
5313
|
-
}
|
5314
|
-
|
5315
|
-
break;
|
5316
|
-
|
5317
|
-
case 'maxlength':
|
5318
|
-
case 'tabindex':
|
5319
|
-
// IE returns default value
|
5320
|
-
if (value === 32768 || value === 2147483647 || value === '32768') {
|
5321
|
-
value = '';
|
5322
|
-
}
|
5323
|
-
|
5324
|
-
break;
|
5325
|
-
|
5326
|
-
case 'multiple':
|
5327
|
-
case 'compact':
|
5328
|
-
case 'noshade':
|
5329
|
-
case 'nowrap':
|
5330
|
-
if (value === 65535) {
|
5331
|
-
return name;
|
5332
|
-
}
|
5333
|
-
|
5334
|
-
return defaultVal;
|
5335
|
-
|
5336
|
-
case 'shape':
|
5337
|
-
value = value.toLowerCase();
|
5338
|
-
break;
|
5339
|
-
|
5340
|
-
default:
|
5341
|
-
// IE has odd anonymous function for event attributes
|
5342
|
-
if (name.indexOf('on') === 0 && value) {
|
5343
|
-
value = ('' + value).replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/, '$1');
|
5344
|
-
}
|
5345
|
-
}
|
5346
|
-
}
|
5347
|
-
|
5348
|
-
return (value !== undef && value !== null && value !== '') ? '' + value : defaultVal;
|
5349
|
-
},
|
5350
|
-
|
5351
|
-
/**
|
5352
|
-
* Returns the absolute x, y position of a node. The position will be returned in an object with x, y fields.
|
5353
|
-
*
|
5354
|
-
* @method getPos
|
5355
|
-
* @param {Element/String} elm HTML element or element id to get x, y position from.
|
5356
|
-
* @param {Element} rootElm Optional root element to stop calculations at.
|
5357
|
-
* @return {object} Absolute position of the specified element object with x, y fields.
|
5358
|
-
*/
|
5359
|
-
getPos: function(elm, rootElm) {
|
5360
|
-
var self = this, x = 0, y = 0, offsetParent, doc = self.doc, pos;
|
5361
|
-
|
5362
|
-
elm = self.get(elm);
|
5363
|
-
rootElm = rootElm || doc.body;
|
5364
|
-
|
5365
|
-
if (elm) {
|
5366
|
-
// Use getBoundingClientRect if it exists since it's faster than looping offset nodes
|
5367
|
-
if (rootElm === doc.body && elm.getBoundingClientRect) {
|
5368
|
-
pos = elm.getBoundingClientRect();
|
5369
|
-
rootElm = self.boxModel ? doc.documentElement : doc.body;
|
5370
|
-
|
5371
|
-
// Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
|
5372
|
-
// Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
|
5373
|
-
x = pos.left + (doc.documentElement.scrollLeft || doc.body.scrollLeft) - rootElm.clientLeft;
|
5374
|
-
y = pos.top + (doc.documentElement.scrollTop || doc.body.scrollTop) - rootElm.clientTop;
|
5375
|
-
|
5376
|
-
return {x: x, y: y};
|
5377
|
-
}
|
5378
|
-
|
5379
|
-
offsetParent = elm;
|
5380
|
-
while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
|
5381
|
-
x += offsetParent.offsetLeft || 0;
|
5382
|
-
y += offsetParent.offsetTop || 0;
|
5383
|
-
offsetParent = offsetParent.offsetParent;
|
5384
|
-
}
|
5385
|
-
|
5386
|
-
offsetParent = elm.parentNode;
|
5387
|
-
while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
|
5388
|
-
x -= offsetParent.scrollLeft || 0;
|
5389
|
-
y -= offsetParent.scrollTop || 0;
|
5390
|
-
offsetParent = offsetParent.parentNode;
|
5391
|
-
}
|
5392
|
-
}
|
5393
|
-
|
5394
|
-
return {x: x, y: y};
|
5395
|
-
},
|
5417
|
+
return {x: x, y: y};
|
5418
|
+
},
|
5396
5419
|
|
5397
5420
|
/**
|
5398
5421
|
* Parses the specified style value into an object collection. This parser will also
|
@@ -5539,22 +5562,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5539
5562
|
* tinymce.DOM.addClass('mydiv', 'myclass');
|
5540
5563
|
*/
|
5541
5564
|
addClass: function(elm, cls) {
|
5542
|
-
|
5543
|
-
var clsVal;
|
5544
|
-
|
5545
|
-
if (!cls) {
|
5546
|
-
return 0;
|
5547
|
-
}
|
5548
|
-
|
5549
|
-
if (this.hasClass(elm, cls)) {
|
5550
|
-
return elm.className;
|
5551
|
-
}
|
5552
|
-
|
5553
|
-
clsVal = this.removeClass(elm, cls);
|
5554
|
-
elm.className = clsVal = (clsVal !== '' ? (clsVal + ' ') : '') + cls;
|
5555
|
-
|
5556
|
-
return clsVal;
|
5557
|
-
});
|
5565
|
+
this.$$(elm).addClass(cls);
|
5558
5566
|
},
|
5559
5567
|
|
5560
5568
|
/**
|
@@ -5573,32 +5581,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5573
5581
|
* tinymce.DOM.removeClass('mydiv', 'myclass');
|
5574
5582
|
*/
|
5575
5583
|
removeClass: function(elm, cls) {
|
5576
|
-
|
5577
|
-
|
5578
|
-
return self.run(elm, function(elm) {
|
5579
|
-
var val;
|
5580
|
-
|
5581
|
-
if (self.hasClass(elm, cls)) {
|
5582
|
-
if (!re) {
|
5583
|
-
re = new RegExp("(^|\\s+)" + cls + "(\\s+|$)", "g");
|
5584
|
-
}
|
5585
|
-
|
5586
|
-
val = elm.className.replace(re, ' ');
|
5587
|
-
val = trim(val != ' ' ? val : '');
|
5588
|
-
|
5589
|
-
elm.className = val;
|
5590
|
-
|
5591
|
-
// Empty class attr
|
5592
|
-
if (!val) {
|
5593
|
-
elm.removeAttribute('class');
|
5594
|
-
elm.removeAttribute('className');
|
5595
|
-
}
|
5596
|
-
|
5597
|
-
return val;
|
5598
|
-
}
|
5599
|
-
|
5600
|
-
return elm.className;
|
5601
|
-
});
|
5584
|
+
this.toggleClass(elm, cls, false);
|
5602
5585
|
},
|
5603
5586
|
|
5604
5587
|
/**
|
@@ -5610,13 +5593,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5610
5593
|
* @return {Boolean} true/false if the specified element has the specified class.
|
5611
5594
|
*/
|
5612
5595
|
hasClass: function(elm, cls) {
|
5613
|
-
|
5614
|
-
|
5615
|
-
if (!elm || !cls) {
|
5616
|
-
return false;
|
5617
|
-
}
|
5618
|
-
|
5619
|
-
return (' ' + elm.className + ' ').indexOf(' ' + cls + ' ') !== -1;
|
5596
|
+
return this.$$(elm).hasClass(cls);
|
5620
5597
|
},
|
5621
5598
|
|
5622
5599
|
/**
|
@@ -5628,15 +5605,11 @@ define("tinymce/dom/DOMUtils", [
|
|
5628
5605
|
* @param {[type]} state Optional state to set.
|
5629
5606
|
*/
|
5630
5607
|
toggleClass: function(elm, cls, state) {
|
5631
|
-
|
5632
|
-
|
5633
|
-
|
5634
|
-
if (state) {
|
5635
|
-
this.addClass(elm, cls);
|
5636
|
-
} else {
|
5637
|
-
this.removeClass(elm, cls);
|
5608
|
+
this.$$(elm).toggleClass(cls, state).each(function() {
|
5609
|
+
if (this.className === '') {
|
5610
|
+
$(this).attr('class', null);
|
5638
5611
|
}
|
5639
|
-
}
|
5612
|
+
});
|
5640
5613
|
},
|
5641
5614
|
|
5642
5615
|
/**
|
@@ -5646,7 +5619,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5646
5619
|
* @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to show.
|
5647
5620
|
*/
|
5648
5621
|
show: function(elm) {
|
5649
|
-
|
5622
|
+
this.$$(elm).show();
|
5650
5623
|
},
|
5651
5624
|
|
5652
5625
|
/**
|
@@ -5659,7 +5632,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5659
5632
|
* tinymce.DOM.hide('myid');
|
5660
5633
|
*/
|
5661
5634
|
hide: function(elm) {
|
5662
|
-
|
5635
|
+
this.$$(elm).hide();
|
5663
5636
|
},
|
5664
5637
|
|
5665
5638
|
/**
|
@@ -5670,9 +5643,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5670
5643
|
* @return {Boolean} true/false if the element is hidden or not.
|
5671
5644
|
*/
|
5672
5645
|
isHidden: function(elm) {
|
5673
|
-
|
5674
|
-
|
5675
|
-
return !elm || elm.style.display == 'none' || this.getStyle(elm, 'display') == 'none';
|
5646
|
+
return this.$$(elm).css('display') == 'none';
|
5676
5647
|
},
|
5677
5648
|
|
5678
5649
|
/**
|
@@ -5692,7 +5663,7 @@ define("tinymce/dom/DOMUtils", [
|
|
5692
5663
|
* URLs will get converted, hex color values fixed etc. Check processHTML for details.
|
5693
5664
|
*
|
5694
5665
|
* @method setHTML
|
5695
|
-
* @param {Element/String/Array}
|
5666
|
+
* @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set HTML inside of.
|
5696
5667
|
* @param {String} h HTML content to set as inner HTML of the element.
|
5697
5668
|
* @example
|
5698
5669
|
* // Sets the inner HTML of all paragraphs in the active editor
|
@@ -5701,44 +5672,35 @@ define("tinymce/dom/DOMUtils", [
|
|
5701
5672
|
* // Sets the inner HTML of an element by id in the document
|
5702
5673
|
* tinymce.DOM.setHTML('mydiv', 'some inner html');
|
5703
5674
|
*/
|
5704
|
-
setHTML: function(
|
5705
|
-
|
5675
|
+
setHTML: function(elm, html) {
|
5676
|
+
elm = this.$$(elm);
|
5677
|
+
|
5678
|
+
if (isIE) {
|
5679
|
+
elm.each(function(i, target) {
|
5680
|
+
if (target.canHaveHTML === false) {
|
5681
|
+
return;
|
5682
|
+
}
|
5706
5683
|
|
5707
|
-
return self.run(element, function(element) {
|
5708
|
-
if (isIE) {
|
5709
5684
|
// Remove all child nodes, IE keeps empty text nodes in DOM
|
5710
|
-
while (
|
5711
|
-
|
5685
|
+
while (target.firstChild) {
|
5686
|
+
target.removeChild(target.firstChild);
|
5712
5687
|
}
|
5713
5688
|
|
5714
5689
|
try {
|
5715
5690
|
// IE will remove comments from the beginning
|
5716
5691
|
// unless you padd the contents with something
|
5717
|
-
|
5718
|
-
|
5692
|
+
target.innerHTML = '<br>' + html;
|
5693
|
+
target.removeChild(target.firstChild);
|
5719
5694
|
} catch (ex) {
|
5720
|
-
// IE sometimes produces an unknown runtime error on innerHTML if it's a
|
5721
|
-
|
5722
|
-
// This seems to fix this problem
|
5723
|
-
|
5724
|
-
// Create new div with HTML contents and a BR in front to keep comments
|
5725
|
-
var newElement = self.create('div');
|
5726
|
-
newElement.innerHTML = '<br />' + html;
|
5727
|
-
|
5728
|
-
// Add all children from div to target
|
5729
|
-
each(grep(newElement.childNodes), function(node, i) {
|
5730
|
-
// Skip br element
|
5731
|
-
if (i && element.canHaveHTML) {
|
5732
|
-
element.appendChild(node);
|
5733
|
-
}
|
5734
|
-
});
|
5695
|
+
// IE sometimes produces an unknown runtime error on innerHTML if it's a div inside a p
|
5696
|
+
$('<div>').html('<br>' + html).contents().slice(1).appendTo(target);
|
5735
5697
|
}
|
5736
|
-
} else {
|
5737
|
-
element.innerHTML = html;
|
5738
|
-
}
|
5739
5698
|
|
5740
|
-
|
5741
|
-
|
5699
|
+
return html;
|
5700
|
+
});
|
5701
|
+
} else {
|
5702
|
+
elm.html(html);
|
5703
|
+
}
|
5742
5704
|
},
|
5743
5705
|
|
5744
5706
|
/**
|
@@ -5752,22 +5714,8 @@ define("tinymce/dom/DOMUtils", [
|
|
5752
5714
|
* tinymce.activeEditor.getOuterHTML(tinymce.activeEditor.getBody());
|
5753
5715
|
*/
|
5754
5716
|
getOuterHTML: function(elm) {
|
5755
|
-
|
5756
|
-
|
5757
|
-
elm = self.get(elm);
|
5758
|
-
|
5759
|
-
if (!elm) {
|
5760
|
-
return null;
|
5761
|
-
}
|
5762
|
-
|
5763
|
-
if (elm.nodeType === 1 && self.hasOuterHTML) {
|
5764
|
-
return elm.outerHTML;
|
5765
|
-
}
|
5766
|
-
|
5767
|
-
doc = (elm.ownerDocument || self.doc).createElement("body");
|
5768
|
-
doc.appendChild(elm.cloneNode(true));
|
5769
|
-
|
5770
|
-
return doc.innerHTML;
|
5717
|
+
elm = this.get(elm);
|
5718
|
+
return elm.nodeType == 1 ? elm.outerHTML : $('<div>').append($(elm).clone()).html();
|
5771
5719
|
},
|
5772
5720
|
|
5773
5721
|
/**
|
@@ -5784,44 +5732,15 @@ define("tinymce/dom/DOMUtils", [
|
|
5784
5732
|
* // Sets the outer HTML of an element by id in the document
|
5785
5733
|
* tinymce.DOM.setOuterHTML('mydiv', '<div>some html</div>');
|
5786
5734
|
*/
|
5787
|
-
setOuterHTML: function(elm, html
|
5735
|
+
setOuterHTML: function(elm, html) {
|
5788
5736
|
var self = this;
|
5789
5737
|
|
5790
|
-
|
5791
|
-
|
5792
|
-
|
5793
|
-
|
5794
|
-
|
5795
|
-
|
5796
|
-
|
5797
|
-
node = tempElm.lastChild;
|
5798
|
-
while (node) {
|
5799
|
-
self.insertAfter(node.cloneNode(true), elm);
|
5800
|
-
node = node.previousSibling;
|
5801
|
-
}
|
5802
|
-
|
5803
|
-
self.remove(elm);
|
5804
|
-
}
|
5805
|
-
|
5806
|
-
// Only set HTML on elements
|
5807
|
-
if (elm.nodeType == 1) {
|
5808
|
-
doc = doc || elm.ownerDocument || self.doc;
|
5809
|
-
|
5810
|
-
if (isIE) {
|
5811
|
-
try {
|
5812
|
-
// Try outerHTML for IE it sometimes produces an unknown runtime error
|
5813
|
-
if (elm.nodeType == 1 && self.hasOuterHTML) {
|
5814
|
-
elm.outerHTML = html;
|
5815
|
-
} else {
|
5816
|
-
set();
|
5817
|
-
}
|
5818
|
-
} catch (ex) {
|
5819
|
-
// Fix for unknown runtime error
|
5820
|
-
set();
|
5821
|
-
}
|
5822
|
-
} else {
|
5823
|
-
set();
|
5824
|
-
}
|
5738
|
+
self.$$(elm).each(function() {
|
5739
|
+
try {
|
5740
|
+
this.outerHTML = html;
|
5741
|
+
} catch (ex) {
|
5742
|
+
// OuterHTML for IE it sometimes produces an "unknown runtime error"
|
5743
|
+
self.remove($(this).html(html), true);
|
5825
5744
|
}
|
5826
5745
|
});
|
5827
5746
|
},
|
@@ -5852,14 +5771,14 @@ define("tinymce/dom/DOMUtils", [
|
|
5852
5771
|
* @param {Element/String/Array} reference_node Reference element, element id or array of elements to insert after.
|
5853
5772
|
* @return {Element/Array} Element that got added or an array with elements.
|
5854
5773
|
*/
|
5855
|
-
insertAfter: function(node,
|
5856
|
-
|
5774
|
+
insertAfter: function(node, referenceNode) {
|
5775
|
+
referenceNode = this.get(referenceNode);
|
5857
5776
|
|
5858
5777
|
return this.run(node, function(node) {
|
5859
5778
|
var parent, nextSibling;
|
5860
5779
|
|
5861
|
-
parent =
|
5862
|
-
nextSibling =
|
5780
|
+
parent = referenceNode.parentNode;
|
5781
|
+
nextSibling = referenceNode.nextSibling;
|
5863
5782
|
|
5864
5783
|
if (nextSibling) {
|
5865
5784
|
parent.insertBefore(node, nextSibling);
|
@@ -5914,8 +5833,8 @@ define("tinymce/dom/DOMUtils", [
|
|
5914
5833
|
newElm = self.create(name);
|
5915
5834
|
|
5916
5835
|
// Copy attribs to new block
|
5917
|
-
each(self.getAttribs(elm), function(
|
5918
|
-
self.setAttrib(newElm,
|
5836
|
+
each(self.getAttribs(elm), function(attrNode) {
|
5837
|
+
self.setAttrib(newElm, attrNode.nodeName, self.getAttrib(elm, attrNode.nodeName));
|
5919
5838
|
});
|
5920
5839
|
|
5921
5840
|
// Replace block
|
@@ -6995,10 +6914,10 @@ define("tinymce/AddOnManager", [
|
|
6995
6914
|
* });
|
6996
6915
|
*/
|
6997
6916
|
|
6998
|
-
// Included from: js/tinymce/classes/
|
6917
|
+
// Included from: js/tinymce/classes/dom/RangeUtils.js
|
6999
6918
|
|
7000
6919
|
/**
|
7001
|
-
*
|
6920
|
+
* RangeUtils.js
|
7002
6921
|
*
|
7003
6922
|
* Copyright, Moxiecode Systems AB
|
7004
6923
|
* Released under LGPL License.
|
@@ -7008,88 +6927,719 @@ define("tinymce/AddOnManager", [
|
|
7008
6927
|
*/
|
7009
6928
|
|
7010
6929
|
/**
|
7011
|
-
* This class
|
7012
|
-
*
|
7013
|
-
* @example
|
7014
|
-
* var node = new tinymce.html.Node('strong', 1);
|
7015
|
-
* someRoot.append(node);
|
6930
|
+
* This class contains a few utility methods for ranges.
|
7016
6931
|
*
|
7017
|
-
* @class tinymce.
|
7018
|
-
* @
|
6932
|
+
* @class tinymce.dom.RangeUtils
|
6933
|
+
* @private
|
7019
6934
|
*/
|
7020
|
-
define("tinymce/
|
7021
|
-
|
7022
|
-
|
7023
|
-
|
7024
|
-
|
7025
|
-
'#pi': 7,
|
7026
|
-
'#doctype': 10,
|
7027
|
-
'#document-fragment': 11
|
7028
|
-
};
|
7029
|
-
|
7030
|
-
// Walks the tree left/right
|
7031
|
-
function walk(node, root_node, prev) {
|
7032
|
-
var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next';
|
7033
|
-
|
7034
|
-
// Walk into nodes if it has a start
|
7035
|
-
if (node[startName]) {
|
7036
|
-
return node[startName];
|
7037
|
-
}
|
7038
|
-
|
7039
|
-
// Return the sibling if it has one
|
7040
|
-
if (node !== root_node) {
|
7041
|
-
sibling = node[siblingName];
|
6935
|
+
define("tinymce/dom/RangeUtils", [
|
6936
|
+
"tinymce/util/Tools",
|
6937
|
+
"tinymce/dom/TreeWalker"
|
6938
|
+
], function(Tools, TreeWalker) {
|
6939
|
+
var each = Tools.each;
|
7042
6940
|
|
7043
|
-
|
7044
|
-
|
7045
|
-
}
|
6941
|
+
function getEndChild(container, index) {
|
6942
|
+
var childNodes = container.childNodes;
|
7046
6943
|
|
7047
|
-
|
7048
|
-
for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) {
|
7049
|
-
sibling = parent[siblingName];
|
6944
|
+
index--;
|
7050
6945
|
|
7051
|
-
|
7052
|
-
|
7053
|
-
|
7054
|
-
|
6946
|
+
if (index > childNodes.length - 1) {
|
6947
|
+
index = childNodes.length - 1;
|
6948
|
+
} else if (index < 0) {
|
6949
|
+
index = 0;
|
7055
6950
|
}
|
7056
|
-
}
|
7057
|
-
|
7058
|
-
/**
|
7059
|
-
* Constructs a new Node instance.
|
7060
|
-
*
|
7061
|
-
* @constructor
|
7062
|
-
* @method Node
|
7063
|
-
* @param {String} name Name of the node type.
|
7064
|
-
* @param {Number} type Numeric type representing the node.
|
7065
|
-
*/
|
7066
|
-
function Node(name, type) {
|
7067
|
-
this.name = name;
|
7068
|
-
this.type = type;
|
7069
6951
|
|
7070
|
-
|
7071
|
-
this.attributes = [];
|
7072
|
-
this.attributes.map = {};
|
7073
|
-
}
|
6952
|
+
return childNodes[index] || container;
|
7074
6953
|
}
|
7075
6954
|
|
7076
|
-
|
6955
|
+
function RangeUtils(dom) {
|
7077
6956
|
/**
|
7078
|
-
*
|
7079
|
-
*
|
7080
|
-
* @example
|
7081
|
-
* someNode.replace(someNewNode);
|
6957
|
+
* Walks the specified range like object and executes the callback for each sibling collection it finds.
|
7082
6958
|
*
|
7083
|
-
* @method
|
7084
|
-
* @param {
|
7085
|
-
* @
|
6959
|
+
* @method walk
|
6960
|
+
* @param {Object} rng Range like object.
|
6961
|
+
* @param {function} callback Callback function to execute for each sibling collection.
|
7086
6962
|
*/
|
7087
|
-
|
7088
|
-
var
|
7089
|
-
|
7090
|
-
|
7091
|
-
|
7092
|
-
|
6963
|
+
this.walk = function(rng, callback) {
|
6964
|
+
var startContainer = rng.startContainer,
|
6965
|
+
startOffset = rng.startOffset,
|
6966
|
+
endContainer = rng.endContainer,
|
6967
|
+
endOffset = rng.endOffset,
|
6968
|
+
ancestor, startPoint,
|
6969
|
+
endPoint, node, parent, siblings, nodes;
|
6970
|
+
|
6971
|
+
// Handle table cell selection the table plugin enables
|
6972
|
+
// you to fake select table cells and perform formatting actions on them
|
6973
|
+
nodes = dom.select('td.mce-item-selected,th.mce-item-selected');
|
6974
|
+
if (nodes.length > 0) {
|
6975
|
+
each(nodes, function(node) {
|
6976
|
+
callback([node]);
|
6977
|
+
});
|
6978
|
+
|
6979
|
+
return;
|
6980
|
+
}
|
6981
|
+
|
6982
|
+
/**
|
6983
|
+
* Excludes start/end text node if they are out side the range
|
6984
|
+
*
|
6985
|
+
* @private
|
6986
|
+
* @param {Array} nodes Nodes to exclude items from.
|
6987
|
+
* @return {Array} Array with nodes excluding the start/end container if needed.
|
6988
|
+
*/
|
6989
|
+
function exclude(nodes) {
|
6990
|
+
var node;
|
6991
|
+
|
6992
|
+
// First node is excluded
|
6993
|
+
node = nodes[0];
|
6994
|
+
if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
|
6995
|
+
nodes.splice(0, 1);
|
6996
|
+
}
|
6997
|
+
|
6998
|
+
// Last node is excluded
|
6999
|
+
node = nodes[nodes.length - 1];
|
7000
|
+
if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
|
7001
|
+
nodes.splice(nodes.length - 1, 1);
|
7002
|
+
}
|
7003
|
+
|
7004
|
+
return nodes;
|
7005
|
+
}
|
7006
|
+
|
7007
|
+
/**
|
7008
|
+
* Collects siblings
|
7009
|
+
*
|
7010
|
+
* @private
|
7011
|
+
* @param {Node} node Node to collect siblings from.
|
7012
|
+
* @param {String} name Name of the sibling to check for.
|
7013
|
+
* @return {Array} Array of collected siblings.
|
7014
|
+
*/
|
7015
|
+
function collectSiblings(node, name, end_node) {
|
7016
|
+
var siblings = [];
|
7017
|
+
|
7018
|
+
for (; node && node != end_node; node = node[name]) {
|
7019
|
+
siblings.push(node);
|
7020
|
+
}
|
7021
|
+
|
7022
|
+
return siblings;
|
7023
|
+
}
|
7024
|
+
|
7025
|
+
/**
|
7026
|
+
* Find an end point this is the node just before the common ancestor root.
|
7027
|
+
*
|
7028
|
+
* @private
|
7029
|
+
* @param {Node} node Node to start at.
|
7030
|
+
* @param {Node} root Root/ancestor element to stop just before.
|
7031
|
+
* @return {Node} Node just before the root element.
|
7032
|
+
*/
|
7033
|
+
function findEndPoint(node, root) {
|
7034
|
+
do {
|
7035
|
+
if (node.parentNode == root) {
|
7036
|
+
return node;
|
7037
|
+
}
|
7038
|
+
|
7039
|
+
node = node.parentNode;
|
7040
|
+
} while (node);
|
7041
|
+
}
|
7042
|
+
|
7043
|
+
function walkBoundary(start_node, end_node, next) {
|
7044
|
+
var siblingName = next ? 'nextSibling' : 'previousSibling';
|
7045
|
+
|
7046
|
+
for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) {
|
7047
|
+
parent = node.parentNode;
|
7048
|
+
siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName);
|
7049
|
+
|
7050
|
+
if (siblings.length) {
|
7051
|
+
if (!next) {
|
7052
|
+
siblings.reverse();
|
7053
|
+
}
|
7054
|
+
|
7055
|
+
callback(exclude(siblings));
|
7056
|
+
}
|
7057
|
+
}
|
7058
|
+
}
|
7059
|
+
|
7060
|
+
// If index based start position then resolve it
|
7061
|
+
if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) {
|
7062
|
+
startContainer = startContainer.childNodes[startOffset];
|
7063
|
+
}
|
7064
|
+
|
7065
|
+
// If index based end position then resolve it
|
7066
|
+
if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
|
7067
|
+
endContainer = getEndChild(endContainer, endOffset);
|
7068
|
+
}
|
7069
|
+
|
7070
|
+
// Same container
|
7071
|
+
if (startContainer == endContainer) {
|
7072
|
+
return callback(exclude([startContainer]));
|
7073
|
+
}
|
7074
|
+
|
7075
|
+
// Find common ancestor and end points
|
7076
|
+
ancestor = dom.findCommonAncestor(startContainer, endContainer);
|
7077
|
+
|
7078
|
+
// Process left side
|
7079
|
+
for (node = startContainer; node; node = node.parentNode) {
|
7080
|
+
if (node === endContainer) {
|
7081
|
+
return walkBoundary(startContainer, ancestor, true);
|
7082
|
+
}
|
7083
|
+
|
7084
|
+
if (node === ancestor) {
|
7085
|
+
break;
|
7086
|
+
}
|
7087
|
+
}
|
7088
|
+
|
7089
|
+
// Process right side
|
7090
|
+
for (node = endContainer; node; node = node.parentNode) {
|
7091
|
+
if (node === startContainer) {
|
7092
|
+
return walkBoundary(endContainer, ancestor);
|
7093
|
+
}
|
7094
|
+
|
7095
|
+
if (node === ancestor) {
|
7096
|
+
break;
|
7097
|
+
}
|
7098
|
+
}
|
7099
|
+
|
7100
|
+
// Find start/end point
|
7101
|
+
startPoint = findEndPoint(startContainer, ancestor) || startContainer;
|
7102
|
+
endPoint = findEndPoint(endContainer, ancestor) || endContainer;
|
7103
|
+
|
7104
|
+
// Walk left leaf
|
7105
|
+
walkBoundary(startContainer, startPoint, true);
|
7106
|
+
|
7107
|
+
// Walk the middle from start to end point
|
7108
|
+
siblings = collectSiblings(
|
7109
|
+
startPoint == startContainer ? startPoint : startPoint.nextSibling,
|
7110
|
+
'nextSibling',
|
7111
|
+
endPoint == endContainer ? endPoint.nextSibling : endPoint
|
7112
|
+
);
|
7113
|
+
|
7114
|
+
if (siblings.length) {
|
7115
|
+
callback(exclude(siblings));
|
7116
|
+
}
|
7117
|
+
|
7118
|
+
// Walk right leaf
|
7119
|
+
walkBoundary(endContainer, endPoint);
|
7120
|
+
};
|
7121
|
+
|
7122
|
+
/**
|
7123
|
+
* Splits the specified range at it's start/end points.
|
7124
|
+
*
|
7125
|
+
* @private
|
7126
|
+
* @param {Range/RangeObject} rng Range to split.
|
7127
|
+
* @return {Object} Range position object.
|
7128
|
+
*/
|
7129
|
+
this.split = function(rng) {
|
7130
|
+
var startContainer = rng.startContainer,
|
7131
|
+
startOffset = rng.startOffset,
|
7132
|
+
endContainer = rng.endContainer,
|
7133
|
+
endOffset = rng.endOffset;
|
7134
|
+
|
7135
|
+
function splitText(node, offset) {
|
7136
|
+
return node.splitText(offset);
|
7137
|
+
}
|
7138
|
+
|
7139
|
+
// Handle single text node
|
7140
|
+
if (startContainer == endContainer && startContainer.nodeType == 3) {
|
7141
|
+
if (startOffset > 0 && startOffset < startContainer.nodeValue.length) {
|
7142
|
+
endContainer = splitText(startContainer, startOffset);
|
7143
|
+
startContainer = endContainer.previousSibling;
|
7144
|
+
|
7145
|
+
if (endOffset > startOffset) {
|
7146
|
+
endOffset = endOffset - startOffset;
|
7147
|
+
startContainer = endContainer = splitText(endContainer, endOffset).previousSibling;
|
7148
|
+
endOffset = endContainer.nodeValue.length;
|
7149
|
+
startOffset = 0;
|
7150
|
+
} else {
|
7151
|
+
endOffset = 0;
|
7152
|
+
}
|
7153
|
+
}
|
7154
|
+
} else {
|
7155
|
+
// Split startContainer text node if needed
|
7156
|
+
if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) {
|
7157
|
+
startContainer = splitText(startContainer, startOffset);
|
7158
|
+
startOffset = 0;
|
7159
|
+
}
|
7160
|
+
|
7161
|
+
// Split endContainer text node if needed
|
7162
|
+
if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) {
|
7163
|
+
endContainer = splitText(endContainer, endOffset).previousSibling;
|
7164
|
+
endOffset = endContainer.nodeValue.length;
|
7165
|
+
}
|
7166
|
+
}
|
7167
|
+
|
7168
|
+
return {
|
7169
|
+
startContainer: startContainer,
|
7170
|
+
startOffset: startOffset,
|
7171
|
+
endContainer: endContainer,
|
7172
|
+
endOffset: endOffset
|
7173
|
+
};
|
7174
|
+
};
|
7175
|
+
|
7176
|
+
/**
|
7177
|
+
* Normalizes the specified range by finding the closest best suitable caret location.
|
7178
|
+
*
|
7179
|
+
* @private
|
7180
|
+
* @param {Range} rng Range to normalize.
|
7181
|
+
* @return {Boolean} True/false if the specified range was normalized or not.
|
7182
|
+
*/
|
7183
|
+
this.normalize = function(rng) {
|
7184
|
+
var normalized, collapsed;
|
7185
|
+
|
7186
|
+
function normalizeEndPoint(start) {
|
7187
|
+
var container, offset, walker, body = dom.getRoot(), node, nonEmptyElementsMap;
|
7188
|
+
var directionLeft, isAfterNode;
|
7189
|
+
|
7190
|
+
function hasBrBeforeAfter(node, left) {
|
7191
|
+
var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body);
|
7192
|
+
|
7193
|
+
while ((node = walker[left ? 'prev' : 'next']())) {
|
7194
|
+
if (node.nodeName === "BR") {
|
7195
|
+
return true;
|
7196
|
+
}
|
7197
|
+
}
|
7198
|
+
}
|
7199
|
+
|
7200
|
+
function isPrevNode(node, name) {
|
7201
|
+
return node.previousSibling && node.previousSibling.nodeName == name;
|
7202
|
+
}
|
7203
|
+
|
7204
|
+
// Walks the dom left/right to find a suitable text node to move the endpoint into
|
7205
|
+
// It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG
|
7206
|
+
function findTextNodeRelative(left, startNode) {
|
7207
|
+
var walker, lastInlineElement, parentBlockContainer;
|
7208
|
+
|
7209
|
+
startNode = startNode || container;
|
7210
|
+
parentBlockContainer = dom.getParent(startNode.parentNode, dom.isBlock) || body;
|
7211
|
+
|
7212
|
+
// Lean left before the BR element if it's the only BR within a block element. Gecko bug: #6680
|
7213
|
+
// This: <p><br>|</p> becomes <p>|<br></p>
|
7214
|
+
if (left && startNode.nodeName == 'BR' && isAfterNode && dom.isEmpty(parentBlockContainer)) {
|
7215
|
+
container = startNode.parentNode;
|
7216
|
+
offset = dom.nodeIndex(startNode);
|
7217
|
+
normalized = true;
|
7218
|
+
return;
|
7219
|
+
}
|
7220
|
+
|
7221
|
+
// Walk left until we hit a text node we can move to or a block/br/img
|
7222
|
+
walker = new TreeWalker(startNode, parentBlockContainer);
|
7223
|
+
while ((node = walker[left ? 'prev' : 'next']())) {
|
7224
|
+
// Break if we hit a non content editable node
|
7225
|
+
if (dom.getContentEditableParent(node) === "false") {
|
7226
|
+
return;
|
7227
|
+
}
|
7228
|
+
|
7229
|
+
// Found text node that has a length
|
7230
|
+
if (node.nodeType === 3 && node.nodeValue.length > 0) {
|
7231
|
+
container = node;
|
7232
|
+
offset = left ? node.nodeValue.length : 0;
|
7233
|
+
normalized = true;
|
7234
|
+
return;
|
7235
|
+
}
|
7236
|
+
|
7237
|
+
// Break if we find a block or a BR/IMG/INPUT etc
|
7238
|
+
if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
|
7239
|
+
return;
|
7240
|
+
}
|
7241
|
+
|
7242
|
+
lastInlineElement = node;
|
7243
|
+
}
|
7244
|
+
|
7245
|
+
// Only fetch the last inline element when in caret mode for now
|
7246
|
+
if (collapsed && lastInlineElement) {
|
7247
|
+
container = lastInlineElement;
|
7248
|
+
normalized = true;
|
7249
|
+
offset = 0;
|
7250
|
+
}
|
7251
|
+
}
|
7252
|
+
|
7253
|
+
container = rng[(start ? 'start' : 'end') + 'Container'];
|
7254
|
+
offset = rng[(start ? 'start' : 'end') + 'Offset'];
|
7255
|
+
isAfterNode = container.nodeType == 1 && offset === container.childNodes.length;
|
7256
|
+
nonEmptyElementsMap = dom.schema.getNonEmptyElements();
|
7257
|
+
directionLeft = start;
|
7258
|
+
|
7259
|
+
if (container.nodeType == 1 && offset > container.childNodes.length - 1) {
|
7260
|
+
directionLeft = false;
|
7261
|
+
}
|
7262
|
+
|
7263
|
+
// If the container is a document move it to the body element
|
7264
|
+
if (container.nodeType === 9) {
|
7265
|
+
container = dom.getRoot();
|
7266
|
+
offset = 0;
|
7267
|
+
}
|
7268
|
+
|
7269
|
+
// If the container is body try move it into the closest text node or position
|
7270
|
+
if (container === body) {
|
7271
|
+
// If start is before/after a image, table etc
|
7272
|
+
if (directionLeft) {
|
7273
|
+
node = container.childNodes[offset > 0 ? offset - 1 : 0];
|
7274
|
+
if (node) {
|
7275
|
+
if (nonEmptyElementsMap[node.nodeName] || node.nodeName == "TABLE") {
|
7276
|
+
return;
|
7277
|
+
}
|
7278
|
+
}
|
7279
|
+
}
|
7280
|
+
|
7281
|
+
// Resolve the index
|
7282
|
+
if (container.hasChildNodes()) {
|
7283
|
+
offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
|
7284
|
+
container = container.childNodes[offset];
|
7285
|
+
offset = 0;
|
7286
|
+
|
7287
|
+
// Don't walk into elements that doesn't have any child nodes like a IMG
|
7288
|
+
if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) {
|
7289
|
+
// Walk the DOM to find a text node to place the caret at or a BR
|
7290
|
+
node = container;
|
7291
|
+
walker = new TreeWalker(container, body);
|
7292
|
+
|
7293
|
+
do {
|
7294
|
+
// Found a text node use that position
|
7295
|
+
if (node.nodeType === 3 && node.nodeValue.length > 0) {
|
7296
|
+
offset = directionLeft ? 0 : node.nodeValue.length;
|
7297
|
+
container = node;
|
7298
|
+
normalized = true;
|
7299
|
+
break;
|
7300
|
+
}
|
7301
|
+
|
7302
|
+
// Found a BR/IMG element that we can place the caret before
|
7303
|
+
if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
|
7304
|
+
offset = dom.nodeIndex(node);
|
7305
|
+
container = node.parentNode;
|
7306
|
+
|
7307
|
+
// Put caret after image when moving the end point
|
7308
|
+
if (node.nodeName == "IMG" && !directionLeft) {
|
7309
|
+
offset++;
|
7310
|
+
}
|
7311
|
+
|
7312
|
+
normalized = true;
|
7313
|
+
break;
|
7314
|
+
}
|
7315
|
+
} while ((node = (directionLeft ? walker.next() : walker.prev())));
|
7316
|
+
}
|
7317
|
+
}
|
7318
|
+
}
|
7319
|
+
|
7320
|
+
// Lean the caret to the left if possible
|
7321
|
+
if (collapsed) {
|
7322
|
+
// So this: <b>x</b><i>|x</i>
|
7323
|
+
// Becomes: <b>x|</b><i>x</i>
|
7324
|
+
// Seems that only gecko has issues with this
|
7325
|
+
if (container.nodeType === 3 && offset === 0) {
|
7326
|
+
findTextNodeRelative(true);
|
7327
|
+
}
|
7328
|
+
|
7329
|
+
// Lean left into empty inline elements when the caret is before a BR
|
7330
|
+
// So this: <i><b></b><i>|<br></i>
|
7331
|
+
// Becomes: <i><b>|</b><i><br></i>
|
7332
|
+
// Seems that only gecko has issues with this.
|
7333
|
+
// Special edge case for <p><a>x</a>|<br></p> since we don't want <p><a>x|</a><br></p>
|
7334
|
+
if (container.nodeType === 1) {
|
7335
|
+
node = container.childNodes[offset];
|
7336
|
+
|
7337
|
+
// Offset is after the containers last child
|
7338
|
+
// then use the previous child for normalization
|
7339
|
+
if (!node) {
|
7340
|
+
node = container.childNodes[offset - 1];
|
7341
|
+
}
|
7342
|
+
|
7343
|
+
if (node && node.nodeName === 'BR' && !isPrevNode(node, 'A') &&
|
7344
|
+
!hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) {
|
7345
|
+
findTextNodeRelative(true, node);
|
7346
|
+
}
|
7347
|
+
}
|
7348
|
+
}
|
7349
|
+
|
7350
|
+
// Lean the start of the selection right if possible
|
7351
|
+
// So this: x[<b>x]</b>
|
7352
|
+
// Becomes: x<b>[x]</b>
|
7353
|
+
if (directionLeft && !collapsed && container.nodeType === 3 && offset === container.nodeValue.length) {
|
7354
|
+
findTextNodeRelative(false);
|
7355
|
+
}
|
7356
|
+
|
7357
|
+
// Set endpoint if it was normalized
|
7358
|
+
if (normalized) {
|
7359
|
+
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
7360
|
+
}
|
7361
|
+
}
|
7362
|
+
|
7363
|
+
collapsed = rng.collapsed;
|
7364
|
+
|
7365
|
+
normalizeEndPoint(true);
|
7366
|
+
|
7367
|
+
if (!collapsed) {
|
7368
|
+
normalizeEndPoint();
|
7369
|
+
}
|
7370
|
+
|
7371
|
+
// If it was collapsed then make sure it still is
|
7372
|
+
if (normalized && collapsed) {
|
7373
|
+
rng.collapse(true);
|
7374
|
+
}
|
7375
|
+
|
7376
|
+
return normalized;
|
7377
|
+
};
|
7378
|
+
}
|
7379
|
+
|
7380
|
+
/**
|
7381
|
+
* Compares two ranges and checks if they are equal.
|
7382
|
+
*
|
7383
|
+
* @static
|
7384
|
+
* @method compareRanges
|
7385
|
+
* @param {DOMRange} rng1 First range to compare.
|
7386
|
+
* @param {DOMRange} rng2 First range to compare.
|
7387
|
+
* @return {Boolean} true/false if the ranges are equal.
|
7388
|
+
*/
|
7389
|
+
RangeUtils.compareRanges = function(rng1, rng2) {
|
7390
|
+
if (rng1 && rng2) {
|
7391
|
+
// Compare native IE ranges
|
7392
|
+
if (rng1.item || rng1.duplicate) {
|
7393
|
+
// Both are control ranges and the selected element matches
|
7394
|
+
if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) {
|
7395
|
+
return true;
|
7396
|
+
}
|
7397
|
+
|
7398
|
+
// Both are text ranges and the range matches
|
7399
|
+
if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) {
|
7400
|
+
return true;
|
7401
|
+
}
|
7402
|
+
} else {
|
7403
|
+
// Compare w3c ranges
|
7404
|
+
return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset;
|
7405
|
+
}
|
7406
|
+
}
|
7407
|
+
|
7408
|
+
return false;
|
7409
|
+
};
|
7410
|
+
|
7411
|
+
return RangeUtils;
|
7412
|
+
});
|
7413
|
+
|
7414
|
+
// Included from: js/tinymce/classes/NodeChange.js
|
7415
|
+
|
7416
|
+
/**
|
7417
|
+
* NodeChange.js
|
7418
|
+
*
|
7419
|
+
* Copyright, Moxiecode Systems AB
|
7420
|
+
* Released under LGPL License.
|
7421
|
+
*
|
7422
|
+
* License: http://www.tinymce.com/license
|
7423
|
+
* Contributing: http://www.tinymce.com/contributing
|
7424
|
+
*/
|
7425
|
+
|
7426
|
+
/**
|
7427
|
+
* This class handles the nodechange event dispatching both manual and though selection change events.
|
7428
|
+
*
|
7429
|
+
* @class tinymce.NodeChange
|
7430
|
+
* @private
|
7431
|
+
*/
|
7432
|
+
define("tinymce/NodeChange", [
|
7433
|
+
"tinymce/dom/RangeUtils"
|
7434
|
+
], function(RangeUtils) {
|
7435
|
+
return function(editor) {
|
7436
|
+
var lastRng, lastPath = [];
|
7437
|
+
|
7438
|
+
/**
|
7439
|
+
* Returns true/false if the current element path has been changed or not.
|
7440
|
+
*
|
7441
|
+
* @private
|
7442
|
+
* @return {Boolean} True if the element path is the same false if it's not.
|
7443
|
+
*/
|
7444
|
+
function isSameElementPath(startElm) {
|
7445
|
+
var i, currentPath;
|
7446
|
+
|
7447
|
+
currentPath = editor.$(startElm).parentsUntil(editor.getBody()).add(startElm);
|
7448
|
+
if (currentPath.length === lastPath.length) {
|
7449
|
+
for (i = currentPath.length; i >= 0; i--) {
|
7450
|
+
if (currentPath[i] !== lastPath[i]) {
|
7451
|
+
break;
|
7452
|
+
}
|
7453
|
+
}
|
7454
|
+
|
7455
|
+
if (i === -1) {
|
7456
|
+
lastPath = currentPath;
|
7457
|
+
return true;
|
7458
|
+
}
|
7459
|
+
}
|
7460
|
+
|
7461
|
+
lastPath = currentPath;
|
7462
|
+
|
7463
|
+
return false;
|
7464
|
+
}
|
7465
|
+
|
7466
|
+
// Gecko doesn't support the "selectionchange" event
|
7467
|
+
if (!('onselectionchange' in editor.getDoc())) {
|
7468
|
+
editor.on('NodeChange Click MouseUp KeyUp', function(e) {
|
7469
|
+
var nativeRng, fakeRng;
|
7470
|
+
|
7471
|
+
// Since DOM Ranges mutate on modification
|
7472
|
+
// of the DOM we need to clone it's contents
|
7473
|
+
nativeRng = editor.selection.getRng();
|
7474
|
+
fakeRng = {
|
7475
|
+
startContainer: nativeRng.startContainer,
|
7476
|
+
startOffset: nativeRng.startOffset,
|
7477
|
+
endContainer: nativeRng.endContainer,
|
7478
|
+
endOffset: nativeRng.endOffset
|
7479
|
+
};
|
7480
|
+
|
7481
|
+
// Always treat nodechange as a selectionchange since applying
|
7482
|
+
// formatting to the current range wouldn't update the range but it's parent
|
7483
|
+
if (e.type == 'nodechange' || !RangeUtils.compareRanges(fakeRng, lastRng)) {
|
7484
|
+
editor.fire('SelectionChange');
|
7485
|
+
}
|
7486
|
+
|
7487
|
+
lastRng = fakeRng;
|
7488
|
+
});
|
7489
|
+
}
|
7490
|
+
|
7491
|
+
// IE has a bug where it fires a selectionchange on right click that has a range at the start of the body
|
7492
|
+
// When the contextmenu event fires the selection is located at the right location
|
7493
|
+
editor.on('contextmenu', function() {
|
7494
|
+
editor.fire('SelectionChange');
|
7495
|
+
});
|
7496
|
+
|
7497
|
+
editor.on('SelectionChange', function() {
|
7498
|
+
var startElm = editor.selection.getStart();
|
7499
|
+
|
7500
|
+
// Selection change might fire when focus is lost so check if the start is still within the body
|
7501
|
+
if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
|
7502
|
+
editor.nodeChanged({selectionChange: true});
|
7503
|
+
}
|
7504
|
+
});
|
7505
|
+
|
7506
|
+
/**
|
7507
|
+
* Distpaches out a onNodeChange event to all observers. This method should be called when you
|
7508
|
+
* need to update the UI states or element path etc.
|
7509
|
+
*
|
7510
|
+
* @method nodeChanged
|
7511
|
+
* @param {Object} args Optional args to pass to NodeChange event handlers.
|
7512
|
+
*/
|
7513
|
+
this.nodeChanged = function(args) {
|
7514
|
+
var selection = editor.selection, node, parents, root;
|
7515
|
+
|
7516
|
+
// Fix for bug #1896577 it seems that this can not be fired while the editor is loading
|
7517
|
+
if (editor.initialized && !editor.settings.disable_nodechange && !editor.settings.readonly) {
|
7518
|
+
// Get start node
|
7519
|
+
root = editor.getBody();
|
7520
|
+
node = selection.getStart() || root;
|
7521
|
+
node = node.ownerDocument != editor.getDoc() ? editor.getBody() : node;
|
7522
|
+
|
7523
|
+
// Edge case for <p>|<img></p>
|
7524
|
+
if (node.nodeName == 'IMG' && selection.isCollapsed()) {
|
7525
|
+
node = node.parentNode;
|
7526
|
+
}
|
7527
|
+
|
7528
|
+
// Get parents and add them to object
|
7529
|
+
parents = [];
|
7530
|
+
editor.dom.getParent(node, function(node) {
|
7531
|
+
if (node === root) {
|
7532
|
+
return true;
|
7533
|
+
}
|
7534
|
+
|
7535
|
+
parents.push(node);
|
7536
|
+
});
|
7537
|
+
|
7538
|
+
args = args || {};
|
7539
|
+
args.element = node;
|
7540
|
+
args.parents = parents;
|
7541
|
+
|
7542
|
+
editor.fire('NodeChange', args);
|
7543
|
+
}
|
7544
|
+
};
|
7545
|
+
};
|
7546
|
+
});
|
7547
|
+
|
7548
|
+
// Included from: js/tinymce/classes/html/Node.js
|
7549
|
+
|
7550
|
+
/**
|
7551
|
+
* Node.js
|
7552
|
+
*
|
7553
|
+
* Copyright, Moxiecode Systems AB
|
7554
|
+
* Released under LGPL License.
|
7555
|
+
*
|
7556
|
+
* License: http://www.tinymce.com/license
|
7557
|
+
* Contributing: http://www.tinymce.com/contributing
|
7558
|
+
*/
|
7559
|
+
|
7560
|
+
/**
|
7561
|
+
* This class is a minimalistic implementation of a DOM like node used by the DomParser class.
|
7562
|
+
*
|
7563
|
+
* @example
|
7564
|
+
* var node = new tinymce.html.Node('strong', 1);
|
7565
|
+
* someRoot.append(node);
|
7566
|
+
*
|
7567
|
+
* @class tinymce.html.Node
|
7568
|
+
* @version 3.4
|
7569
|
+
*/
|
7570
|
+
define("tinymce/html/Node", [], function() {
|
7571
|
+
var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = {
|
7572
|
+
'#text': 3,
|
7573
|
+
'#comment': 8,
|
7574
|
+
'#cdata': 4,
|
7575
|
+
'#pi': 7,
|
7576
|
+
'#doctype': 10,
|
7577
|
+
'#document-fragment': 11
|
7578
|
+
};
|
7579
|
+
|
7580
|
+
// Walks the tree left/right
|
7581
|
+
function walk(node, root_node, prev) {
|
7582
|
+
var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next';
|
7583
|
+
|
7584
|
+
// Walk into nodes if it has a start
|
7585
|
+
if (node[startName]) {
|
7586
|
+
return node[startName];
|
7587
|
+
}
|
7588
|
+
|
7589
|
+
// Return the sibling if it has one
|
7590
|
+
if (node !== root_node) {
|
7591
|
+
sibling = node[siblingName];
|
7592
|
+
|
7593
|
+
if (sibling) {
|
7594
|
+
return sibling;
|
7595
|
+
}
|
7596
|
+
|
7597
|
+
// Walk up the parents to look for siblings
|
7598
|
+
for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) {
|
7599
|
+
sibling = parent[siblingName];
|
7600
|
+
|
7601
|
+
if (sibling) {
|
7602
|
+
return sibling;
|
7603
|
+
}
|
7604
|
+
}
|
7605
|
+
}
|
7606
|
+
}
|
7607
|
+
|
7608
|
+
/**
|
7609
|
+
* Constructs a new Node instance.
|
7610
|
+
*
|
7611
|
+
* @constructor
|
7612
|
+
* @method Node
|
7613
|
+
* @param {String} name Name of the node type.
|
7614
|
+
* @param {Number} type Numeric type representing the node.
|
7615
|
+
*/
|
7616
|
+
function Node(name, type) {
|
7617
|
+
this.name = name;
|
7618
|
+
this.type = type;
|
7619
|
+
|
7620
|
+
if (type === 1) {
|
7621
|
+
this.attributes = [];
|
7622
|
+
this.attributes.map = {};
|
7623
|
+
}
|
7624
|
+
}
|
7625
|
+
|
7626
|
+
Node.prototype = {
|
7627
|
+
/**
|
7628
|
+
* Replaces the current node with the specified one.
|
7629
|
+
*
|
7630
|
+
* @example
|
7631
|
+
* someNode.replace(someNewNode);
|
7632
|
+
*
|
7633
|
+
* @method replace
|
7634
|
+
* @param {tinymce.html.Node} node Node to replace the current node with.
|
7635
|
+
* @return {tinymce.html.Node} The old node that got replaced.
|
7636
|
+
*/
|
7637
|
+
replace: function(node) {
|
7638
|
+
var self = this;
|
7639
|
+
|
7640
|
+
if (node.parent) {
|
7641
|
+
node.remove();
|
7642
|
+
}
|
7093
7643
|
|
7094
7644
|
self.insert(node, self);
|
7095
7645
|
self.remove();
|
@@ -7907,16 +8457,16 @@ define("tinymce/html/Schema", [
|
|
7907
8457
|
|
7908
8458
|
// Parses the specified valid_elements string and adds to the current rules
|
7909
8459
|
// This function is a bit hard to read since it's heavily optimized for speed
|
7910
|
-
function addValidElements(
|
8460
|
+
function addValidElements(validElements) {
|
7911
8461
|
var ei, el, ai, al, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder,
|
7912
8462
|
prefix, outputName, globalAttributes, globalAttributesOrder, key, value,
|
7913
8463
|
elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,
|
7914
8464
|
attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,
|
7915
8465
|
hasPatternsRegExp = /[*?+]/;
|
7916
8466
|
|
7917
|
-
if (
|
8467
|
+
if (validElements) {
|
7918
8468
|
// Split valid elements into an array with rules
|
7919
|
-
|
8469
|
+
validElements = split(validElements, ',');
|
7920
8470
|
|
7921
8471
|
if (elements['@']) {
|
7922
8472
|
globalAttributes = elements['@'].attributes;
|
@@ -7924,9 +8474,9 @@ define("tinymce/html/Schema", [
|
|
7924
8474
|
}
|
7925
8475
|
|
7926
8476
|
// Loop all rules
|
7927
|
-
for (ei = 0, el =
|
8477
|
+
for (ei = 0, el = validElements.length; ei < el; ei++) {
|
7928
8478
|
// Parse element rule
|
7929
|
-
matches = elementRuleRegExp.exec(
|
8479
|
+
matches = elementRuleRegExp.exec(validElements[ei]);
|
7930
8480
|
if (matches) {
|
7931
8481
|
// Setup local names for matches
|
7932
8482
|
prefix = matches[1];
|
@@ -8056,11 +8606,11 @@ define("tinymce/html/Schema", [
|
|
8056
8606
|
}
|
8057
8607
|
}
|
8058
8608
|
|
8059
|
-
function setValidElements(
|
8609
|
+
function setValidElements(validElements) {
|
8060
8610
|
elements = {};
|
8061
8611
|
patternElements = [];
|
8062
8612
|
|
8063
|
-
addValidElements(
|
8613
|
+
addValidElements(validElements);
|
8064
8614
|
|
8065
8615
|
each(schemaItems, function(element, name) {
|
8066
8616
|
children[name] = element.children;
|
@@ -8068,14 +8618,14 @@ define("tinymce/html/Schema", [
|
|
8068
8618
|
}
|
8069
8619
|
|
8070
8620
|
// Adds custom non HTML elements to the schema
|
8071
|
-
function addCustomElements(
|
8621
|
+
function addCustomElements(customElements) {
|
8072
8622
|
var customElementRegExp = /^(~)?(.+)$/;
|
8073
8623
|
|
8074
|
-
if (
|
8624
|
+
if (customElements) {
|
8075
8625
|
// Flush cached items since we are altering the default maps
|
8076
8626
|
mapCache.text_block_elements = mapCache.block_elements = null;
|
8077
8627
|
|
8078
|
-
each(split(
|
8628
|
+
each(split(customElements, ','), function(rule) {
|
8079
8629
|
var matches = customElementRegExp.exec(rule),
|
8080
8630
|
inline = matches[1] === '~',
|
8081
8631
|
cloneName = inline ? 'span' : 'div',
|
@@ -8113,11 +8663,11 @@ define("tinymce/html/Schema", [
|
|
8113
8663
|
}
|
8114
8664
|
|
8115
8665
|
// Adds valid children to the schema object
|
8116
|
-
function addValidChildren(
|
8666
|
+
function addValidChildren(validChildren) {
|
8117
8667
|
var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/;
|
8118
8668
|
|
8119
|
-
if (
|
8120
|
-
each(split(
|
8669
|
+
if (validChildren) {
|
8670
|
+
each(split(validChildren, ','), function(rule) {
|
8121
8671
|
var matches = childRuleRegExp.exec(rule), parent, prefix;
|
8122
8672
|
|
8123
8673
|
if (matches) {
|
@@ -8562,7 +9112,7 @@ define("tinymce/html/SaxParser", [
|
|
8562
9112
|
var count = 1, index, matches, tokenRegExp, shortEndedElements;
|
8563
9113
|
|
8564
9114
|
shortEndedElements = schema.getShortEndedElements();
|
8565
|
-
tokenRegExp = /<([!?\/])?([A-Za-z0-9
|
9115
|
+
tokenRegExp = /<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
|
8566
9116
|
tokenRegExp.lastIndex = index = startIndex;
|
8567
9117
|
|
8568
9118
|
while ((matches = tokenRegExp.exec(html))) {
|
@@ -8730,7 +9280,7 @@ define("tinymce/html/SaxParser", [
|
|
8730
9280
|
'(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
|
8731
9281
|
'(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
|
8732
9282
|
'(?:\\/([^>]+)>)|' + // End element
|
8733
|
-
'(?:([A-Za-z0-9
|
9283
|
+
'(?:([A-Za-z0-9\\-_\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
|
8734
9284
|
')', 'g');
|
8735
9285
|
|
8736
9286
|
attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
|
@@ -11338,7 +11888,11 @@ define("tinymce/dom/ControlSelection", [
|
|
11338
11888
|
ratio = startH / startW;
|
11339
11889
|
selectedHandle = handle;
|
11340
11890
|
|
11341
|
-
handle.startPos =
|
11891
|
+
handle.startPos = {
|
11892
|
+
x: targetWidth * handle[0] + selectedElmX,
|
11893
|
+
y: targetHeight * handle[1] + selectedElmY
|
11894
|
+
};
|
11895
|
+
|
11342
11896
|
startScrollWidth = rootElement.scrollWidth;
|
11343
11897
|
startScrollHeight = rootElement.scrollHeight;
|
11344
11898
|
|
@@ -11461,7 +12015,7 @@ define("tinymce/dom/ControlSelection", [
|
|
11461
12015
|
});
|
11462
12016
|
|
11463
12017
|
controlElm = e.type == 'mousedown' ? e.target : selection.getNode();
|
11464
|
-
controlElm = dom.
|
12018
|
+
controlElm = dom.$(controlElm).closest(isIE ? 'table' : 'table,img,hr')[0];
|
11465
12019
|
|
11466
12020
|
if (isChildOrEqual(controlElm, rootElement)) {
|
11467
12021
|
disableGeckoResize();
|
@@ -11511,6 +12065,11 @@ define("tinymce/dom/ControlSelection", [
|
|
11511
12065
|
|
11512
12066
|
// Remove native selection and let the magic begin
|
11513
12067
|
resizeStarted = true;
|
12068
|
+
editor.fire('ObjectResizeStart', {
|
12069
|
+
target: selectedElm,
|
12070
|
+
width: selectedElm.clientWidth,
|
12071
|
+
height: selectedElm.clientHeight
|
12072
|
+
});
|
11514
12073
|
editor.getDoc().selection.empty();
|
11515
12074
|
showResizeRect(target, name, lastMouseDownEvent);
|
11516
12075
|
}
|
@@ -11519,6 +12078,7 @@ define("tinymce/dom/ControlSelection", [
|
|
11519
12078
|
var target = e.srcElement;
|
11520
12079
|
|
11521
12080
|
if (target != selectedElm) {
|
12081
|
+
editor.fire('ObjectSelected', {target: target});
|
11522
12082
|
detachResizeStartListener();
|
11523
12083
|
|
11524
12084
|
if (target.id.indexOf('mceResizeHandle') === 0) {
|
@@ -11599,7 +12159,7 @@ define("tinymce/dom/ControlSelection", [
|
|
11599
12159
|
editor.on('mouseup', function(e) {
|
11600
12160
|
var nodeName = e.target.nodeName;
|
11601
12161
|
|
11602
|
-
if (/^(TABLE|IMG|HR)$/.test(nodeName)) {
|
12162
|
+
if (!resizeStarted && /^(TABLE|IMG|HR)$/.test(nodeName)) {
|
11603
12163
|
editor.selection.select(e.target, nodeName == 'TABLE');
|
11604
12164
|
editor.nodeChanged();
|
11605
12165
|
}
|
@@ -11658,10 +12218,10 @@ define("tinymce/dom/ControlSelection", [
|
|
11658
12218
|
};
|
11659
12219
|
});
|
11660
12220
|
|
11661
|
-
// Included from: js/tinymce/classes/dom/
|
12221
|
+
// Included from: js/tinymce/classes/dom/BookmarkManager.js
|
11662
12222
|
|
11663
12223
|
/**
|
11664
|
-
*
|
12224
|
+
* BookmarkManager.js
|
11665
12225
|
*
|
11666
12226
|
* Copyright, Moxiecode Systems AB
|
11667
12227
|
* Released under LGPL License.
|
@@ -11671,880 +12231,383 @@ define("tinymce/dom/ControlSelection", [
|
|
11671
12231
|
*/
|
11672
12232
|
|
11673
12233
|
/**
|
11674
|
-
* This class
|
12234
|
+
* This class handles selection bookmarks.
|
11675
12235
|
*
|
11676
|
-
* @class tinymce.dom.
|
11677
|
-
* @private
|
12236
|
+
* @class tinymce.dom.BookmarkManager
|
11678
12237
|
*/
|
11679
|
-
define("tinymce/dom/
|
11680
|
-
"tinymce/
|
11681
|
-
"tinymce/
|
11682
|
-
], function(
|
11683
|
-
|
11684
|
-
|
11685
|
-
|
11686
|
-
|
11687
|
-
|
11688
|
-
|
11689
|
-
|
11690
|
-
|
11691
|
-
|
11692
|
-
} else if (index < 0) {
|
11693
|
-
index = 0;
|
11694
|
-
}
|
11695
|
-
|
11696
|
-
return childNodes[index] || container;
|
11697
|
-
}
|
12238
|
+
define("tinymce/dom/BookmarkManager", [
|
12239
|
+
"tinymce/Env",
|
12240
|
+
"tinymce/util/Tools"
|
12241
|
+
], function(Env, Tools) {
|
12242
|
+
/**
|
12243
|
+
* Constructs a new BookmarkManager instance for a specific selection instance.
|
12244
|
+
*
|
12245
|
+
* @constructor
|
12246
|
+
* @method BookmarkManager
|
12247
|
+
* @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
|
12248
|
+
*/
|
12249
|
+
function BookmarkManager(selection) {
|
12250
|
+
var dom = selection.dom;
|
11698
12251
|
|
11699
|
-
function RangeUtils(dom) {
|
11700
12252
|
/**
|
11701
|
-
*
|
12253
|
+
* Returns a bookmark location for the current selection. This bookmark object
|
12254
|
+
* can then be used to restore the selection after some content modification to the document.
|
11702
12255
|
*
|
11703
|
-
* @method
|
11704
|
-
* @param {
|
11705
|
-
* @param {
|
12256
|
+
* @method getBookmark
|
12257
|
+
* @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
|
12258
|
+
* @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
|
12259
|
+
* @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
|
12260
|
+
* @example
|
12261
|
+
* // Stores a bookmark of the current selection
|
12262
|
+
* var bm = tinymce.activeEditor.selection.getBookmark();
|
12263
|
+
*
|
12264
|
+
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
12265
|
+
*
|
12266
|
+
* // Restore the selection bookmark
|
12267
|
+
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
11706
12268
|
*/
|
11707
|
-
this.
|
11708
|
-
var
|
11709
|
-
startOffset = rng.startOffset,
|
11710
|
-
endContainer = rng.endContainer,
|
11711
|
-
endOffset = rng.endOffset,
|
11712
|
-
ancestor, startPoint,
|
11713
|
-
endPoint, node, parent, siblings, nodes;
|
11714
|
-
|
11715
|
-
// Handle table cell selection the table plugin enables
|
11716
|
-
// you to fake select table cells and perform formatting actions on them
|
11717
|
-
nodes = dom.select('td.mce-item-selected,th.mce-item-selected');
|
11718
|
-
if (nodes.length > 0) {
|
11719
|
-
each(nodes, function(node) {
|
11720
|
-
callback([node]);
|
11721
|
-
});
|
11722
|
-
|
11723
|
-
return;
|
11724
|
-
}
|
12269
|
+
this.getBookmark = function(type, normalized) {
|
12270
|
+
var rng, rng2, id, collapsed, name, element, chr = '', styles;
|
11725
12271
|
|
11726
|
-
|
11727
|
-
|
11728
|
-
*
|
11729
|
-
* @private
|
11730
|
-
* @param {Array} nodes Nodes to exclude items from.
|
11731
|
-
* @return {Array} Array with nodes excluding the start/end container if needed.
|
11732
|
-
*/
|
11733
|
-
function exclude(nodes) {
|
11734
|
-
var node;
|
11735
|
-
|
11736
|
-
// First node is excluded
|
11737
|
-
node = nodes[0];
|
11738
|
-
if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
|
11739
|
-
nodes.splice(0, 1);
|
11740
|
-
}
|
11741
|
-
|
11742
|
-
// Last node is excluded
|
11743
|
-
node = nodes[nodes.length - 1];
|
11744
|
-
if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
|
11745
|
-
nodes.splice(nodes.length - 1, 1);
|
11746
|
-
}
|
11747
|
-
|
11748
|
-
return nodes;
|
11749
|
-
}
|
11750
|
-
|
11751
|
-
/**
|
11752
|
-
* Collects siblings
|
11753
|
-
*
|
11754
|
-
* @private
|
11755
|
-
* @param {Node} node Node to collect siblings from.
|
11756
|
-
* @param {String} name Name of the sibling to check for.
|
11757
|
-
* @return {Array} Array of collected siblings.
|
11758
|
-
*/
|
11759
|
-
function collectSiblings(node, name, end_node) {
|
11760
|
-
var siblings = [];
|
11761
|
-
|
11762
|
-
for (; node && node != end_node; node = node[name]) {
|
11763
|
-
siblings.push(node);
|
11764
|
-
}
|
11765
|
-
|
11766
|
-
return siblings;
|
11767
|
-
}
|
12272
|
+
function findIndex(name, element) {
|
12273
|
+
var index = 0;
|
11768
12274
|
|
11769
|
-
|
11770
|
-
|
11771
|
-
|
11772
|
-
* @private
|
11773
|
-
* @param {Node} node Node to start at.
|
11774
|
-
* @param {Node} root Root/ancestor element to stop just before.
|
11775
|
-
* @return {Node} Node just before the root element.
|
11776
|
-
*/
|
11777
|
-
function findEndPoint(node, root) {
|
11778
|
-
do {
|
11779
|
-
if (node.parentNode == root) {
|
11780
|
-
return node;
|
12275
|
+
Tools.each(dom.select(name), function(node, i) {
|
12276
|
+
if (node == element) {
|
12277
|
+
index = i;
|
11781
12278
|
}
|
12279
|
+
});
|
11782
12280
|
|
11783
|
-
|
11784
|
-
} while (node);
|
12281
|
+
return index;
|
11785
12282
|
}
|
11786
12283
|
|
11787
|
-
function
|
11788
|
-
|
11789
|
-
|
11790
|
-
for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) {
|
11791
|
-
parent = node.parentNode;
|
11792
|
-
siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName);
|
11793
|
-
|
11794
|
-
if (siblings.length) {
|
11795
|
-
if (!next) {
|
11796
|
-
siblings.reverse();
|
11797
|
-
}
|
12284
|
+
function normalizeTableCellSelection(rng) {
|
12285
|
+
function moveEndPoint(start) {
|
12286
|
+
var container, offset, childNodes, prefix = start ? 'start' : 'end';
|
11798
12287
|
|
11799
|
-
|
12288
|
+
container = rng[prefix + 'Container'];
|
12289
|
+
offset = rng[prefix + 'Offset'];
|
12290
|
+
|
12291
|
+
if (container.nodeType == 1 && container.nodeName == "TR") {
|
12292
|
+
childNodes = container.childNodes;
|
12293
|
+
container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
|
12294
|
+
if (container) {
|
12295
|
+
offset = start ? 0 : container.childNodes.length;
|
12296
|
+
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
12297
|
+
}
|
11800
12298
|
}
|
11801
12299
|
}
|
11802
|
-
}
|
11803
12300
|
|
11804
|
-
|
11805
|
-
|
11806
|
-
startContainer = startContainer.childNodes[startOffset];
|
11807
|
-
}
|
12301
|
+
moveEndPoint(true);
|
12302
|
+
moveEndPoint();
|
11808
12303
|
|
11809
|
-
|
11810
|
-
if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
|
11811
|
-
endContainer = getEndChild(endContainer, endOffset);
|
12304
|
+
return rng;
|
11812
12305
|
}
|
11813
12306
|
|
11814
|
-
|
11815
|
-
|
11816
|
-
return callback(exclude([startContainer]));
|
11817
|
-
}
|
12307
|
+
function getLocation() {
|
12308
|
+
var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
|
11818
12309
|
|
11819
|
-
|
11820
|
-
|
12310
|
+
function getPoint(rng, start) {
|
12311
|
+
var container = rng[start ? 'startContainer' : 'endContainer'],
|
12312
|
+
offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
|
11821
12313
|
|
11822
|
-
|
11823
|
-
|
11824
|
-
|
11825
|
-
|
11826
|
-
|
12314
|
+
if (container.nodeType == 3) {
|
12315
|
+
if (normalized) {
|
12316
|
+
for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
|
12317
|
+
offset += node.nodeValue.length;
|
12318
|
+
}
|
12319
|
+
}
|
11827
12320
|
|
11828
|
-
|
11829
|
-
|
11830
|
-
|
11831
|
-
}
|
12321
|
+
point.push(offset);
|
12322
|
+
} else {
|
12323
|
+
childNodes = container.childNodes;
|
11832
12324
|
|
11833
|
-
|
11834
|
-
|
11835
|
-
|
11836
|
-
|
12325
|
+
if (offset >= childNodes.length && childNodes.length) {
|
12326
|
+
after = 1;
|
12327
|
+
offset = Math.max(0, childNodes.length - 1);
|
12328
|
+
}
|
12329
|
+
|
12330
|
+
point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
|
12331
|
+
}
|
12332
|
+
|
12333
|
+
for (; container && container != root; container = container.parentNode) {
|
12334
|
+
point.push(dom.nodeIndex(container, normalized));
|
12335
|
+
}
|
12336
|
+
|
12337
|
+
return point;
|
11837
12338
|
}
|
11838
12339
|
|
11839
|
-
|
11840
|
-
|
12340
|
+
bookmark.start = getPoint(rng, true);
|
12341
|
+
|
12342
|
+
if (!selection.isCollapsed()) {
|
12343
|
+
bookmark.end = getPoint(rng);
|
11841
12344
|
}
|
12345
|
+
|
12346
|
+
return bookmark;
|
11842
12347
|
}
|
11843
12348
|
|
11844
|
-
|
11845
|
-
|
11846
|
-
|
12349
|
+
if (type == 2) {
|
12350
|
+
element = selection.getNode();
|
12351
|
+
name = element ? element.nodeName : null;
|
11847
12352
|
|
11848
|
-
|
11849
|
-
|
12353
|
+
if (name == 'IMG') {
|
12354
|
+
return {name: name, index: findIndex(name, element)};
|
12355
|
+
}
|
11850
12356
|
|
11851
|
-
|
11852
|
-
|
11853
|
-
|
11854
|
-
'nextSibling',
|
11855
|
-
endPoint == endContainer ? endPoint.nextSibling : endPoint
|
11856
|
-
);
|
12357
|
+
if (selection.tridentSel) {
|
12358
|
+
return selection.tridentSel.getBookmark(type);
|
12359
|
+
}
|
11857
12360
|
|
11858
|
-
|
11859
|
-
callback(exclude(siblings));
|
12361
|
+
return getLocation();
|
11860
12362
|
}
|
11861
12363
|
|
11862
|
-
//
|
11863
|
-
|
11864
|
-
|
12364
|
+
// Handle simple range
|
12365
|
+
if (type) {
|
12366
|
+
return {rng: selection.getRng()};
|
12367
|
+
}
|
11865
12368
|
|
11866
|
-
|
11867
|
-
|
11868
|
-
|
11869
|
-
|
11870
|
-
* @param {Range/RangeObject} rng Range to split.
|
11871
|
-
* @return {Object} Range position object.
|
11872
|
-
*/
|
11873
|
-
this.split = function(rng) {
|
11874
|
-
var startContainer = rng.startContainer,
|
11875
|
-
startOffset = rng.startOffset,
|
11876
|
-
endContainer = rng.endContainer,
|
11877
|
-
endOffset = rng.endOffset;
|
12369
|
+
rng = selection.getRng();
|
12370
|
+
id = dom.uniqueId();
|
12371
|
+
collapsed = selection.isCollapsed();
|
12372
|
+
styles = 'overflow:hidden;line-height:0px';
|
11878
12373
|
|
11879
|
-
|
11880
|
-
|
11881
|
-
|
12374
|
+
// Explorer method
|
12375
|
+
if (rng.duplicate || rng.item) {
|
12376
|
+
// Text selection
|
12377
|
+
if (!rng.item) {
|
12378
|
+
rng2 = rng.duplicate();
|
11882
12379
|
|
11883
|
-
|
11884
|
-
|
11885
|
-
|
11886
|
-
|
11887
|
-
|
12380
|
+
try {
|
12381
|
+
// Insert start marker
|
12382
|
+
rng.collapse();
|
12383
|
+
rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
|
12384
|
+
|
12385
|
+
// Insert end marker
|
12386
|
+
if (!collapsed) {
|
12387
|
+
rng2.collapse(false);
|
12388
|
+
|
12389
|
+
// Detect the empty space after block elements in IE and move the
|
12390
|
+
// end back one character <p></p>] becomes <p>]</p>
|
12391
|
+
rng.moveToElementText(rng2.parentElement());
|
12392
|
+
if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
|
12393
|
+
rng2.move('character', -1);
|
12394
|
+
}
|
11888
12395
|
|
11889
|
-
|
11890
|
-
|
11891
|
-
|
11892
|
-
|
11893
|
-
|
11894
|
-
} else {
|
11895
|
-
endOffset = 0;
|
12396
|
+
rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
|
12397
|
+
}
|
12398
|
+
} catch (ex) {
|
12399
|
+
// IE might throw unspecified error so lets ignore it
|
12400
|
+
return null;
|
11896
12401
|
}
|
12402
|
+
} else {
|
12403
|
+
// Control selection
|
12404
|
+
element = rng.item(0);
|
12405
|
+
name = element.nodeName;
|
12406
|
+
|
12407
|
+
return {name: name, index: findIndex(name, element)};
|
11897
12408
|
}
|
11898
12409
|
} else {
|
11899
|
-
|
11900
|
-
|
11901
|
-
|
11902
|
-
|
12410
|
+
element = selection.getNode();
|
12411
|
+
name = element.nodeName;
|
12412
|
+
if (name == 'IMG') {
|
12413
|
+
return {name: name, index: findIndex(name, element)};
|
11903
12414
|
}
|
11904
12415
|
|
11905
|
-
//
|
11906
|
-
|
11907
|
-
|
11908
|
-
|
12416
|
+
// W3C method
|
12417
|
+
rng2 = normalizeTableCellSelection(rng.cloneRange());
|
12418
|
+
|
12419
|
+
// Insert end marker
|
12420
|
+
if (!collapsed) {
|
12421
|
+
rng2.collapse(false);
|
12422
|
+
rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
|
11909
12423
|
}
|
12424
|
+
|
12425
|
+
rng = normalizeTableCellSelection(rng);
|
12426
|
+
rng.collapse(true);
|
12427
|
+
rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
|
11910
12428
|
}
|
11911
12429
|
|
11912
|
-
|
11913
|
-
|
11914
|
-
|
11915
|
-
endContainer: endContainer,
|
11916
|
-
endOffset: endOffset
|
11917
|
-
};
|
12430
|
+
selection.moveToBookmark({id: id, keep: 1});
|
12431
|
+
|
12432
|
+
return {id: id};
|
11918
12433
|
};
|
11919
12434
|
|
11920
12435
|
/**
|
11921
|
-
*
|
12436
|
+
* Restores the selection to the specified bookmark.
|
11922
12437
|
*
|
11923
|
-
* @
|
11924
|
-
* @param {
|
11925
|
-
* @return {Boolean}
|
12438
|
+
* @method moveToBookmark
|
12439
|
+
* @param {Object} bookmark Bookmark to restore selection from.
|
12440
|
+
* @return {Boolean} true/false if it was successful or not.
|
12441
|
+
* @example
|
12442
|
+
* // Stores a bookmark of the current selection
|
12443
|
+
* var bm = tinymce.activeEditor.selection.getBookmark();
|
12444
|
+
*
|
12445
|
+
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
12446
|
+
*
|
12447
|
+
* // Restore the selection bookmark
|
12448
|
+
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
11926
12449
|
*/
|
11927
|
-
this.
|
11928
|
-
var
|
11929
|
-
|
11930
|
-
function normalizeEndPoint(start) {
|
11931
|
-
var container, offset, walker, body = dom.getRoot(), node, nonEmptyElementsMap;
|
11932
|
-
var directionLeft, isAfterNode;
|
11933
|
-
|
11934
|
-
function hasBrBeforeAfter(node, left) {
|
11935
|
-
var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body);
|
11936
|
-
|
11937
|
-
while ((node = walker[left ? 'prev' : 'next']())) {
|
11938
|
-
if (node.nodeName === "BR") {
|
11939
|
-
return true;
|
11940
|
-
}
|
11941
|
-
}
|
11942
|
-
}
|
11943
|
-
|
11944
|
-
function isPrevNode(node, name) {
|
11945
|
-
return node.previousSibling && node.previousSibling.nodeName == name;
|
11946
|
-
}
|
11947
|
-
|
11948
|
-
// Walks the dom left/right to find a suitable text node to move the endpoint into
|
11949
|
-
// It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG
|
11950
|
-
function findTextNodeRelative(left, startNode) {
|
11951
|
-
var walker, lastInlineElement, parentBlockContainer;
|
11952
|
-
|
11953
|
-
startNode = startNode || container;
|
11954
|
-
parentBlockContainer = dom.getParent(startNode.parentNode, dom.isBlock) || body;
|
12450
|
+
this.moveToBookmark = function(bookmark) {
|
12451
|
+
var rng, root, startContainer, endContainer, startOffset, endOffset;
|
11955
12452
|
|
11956
|
-
|
11957
|
-
|
11958
|
-
if (left && startNode.nodeName == 'BR' && isAfterNode && dom.isEmpty(parentBlockContainer)) {
|
11959
|
-
container = startNode.parentNode;
|
11960
|
-
offset = dom.nodeIndex(startNode);
|
11961
|
-
normalized = true;
|
11962
|
-
return;
|
11963
|
-
}
|
12453
|
+
function setEndPoint(start) {
|
12454
|
+
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
|
11964
12455
|
|
11965
|
-
|
11966
|
-
|
11967
|
-
while ((node = walker[left ? 'prev' : 'next']())) {
|
11968
|
-
// Break if we hit a non content editable node
|
11969
|
-
if (dom.getContentEditableParent(node) === "false") {
|
11970
|
-
return;
|
11971
|
-
}
|
12456
|
+
if (point) {
|
12457
|
+
offset = point[0];
|
11972
12458
|
|
11973
|
-
|
11974
|
-
|
11975
|
-
|
11976
|
-
offset = left ? node.nodeValue.length : 0;
|
11977
|
-
normalized = true;
|
11978
|
-
return;
|
11979
|
-
}
|
12459
|
+
// Find container node
|
12460
|
+
for (node = root, i = point.length - 1; i >= 1; i--) {
|
12461
|
+
children = node.childNodes;
|
11980
12462
|
|
11981
|
-
|
11982
|
-
if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
|
12463
|
+
if (point[i] > children.length - 1) {
|
11983
12464
|
return;
|
11984
12465
|
}
|
11985
12466
|
|
11986
|
-
|
12467
|
+
node = children[point[i]];
|
11987
12468
|
}
|
11988
12469
|
|
11989
|
-
//
|
11990
|
-
if (
|
11991
|
-
|
11992
|
-
normalized = true;
|
11993
|
-
offset = 0;
|
12470
|
+
// Move text offset to best suitable location
|
12471
|
+
if (node.nodeType === 3) {
|
12472
|
+
offset = Math.min(point[0], node.nodeValue.length);
|
11994
12473
|
}
|
11995
|
-
}
|
11996
|
-
|
11997
|
-
container = rng[(start ? 'start' : 'end') + 'Container'];
|
11998
|
-
offset = rng[(start ? 'start' : 'end') + 'Offset'];
|
11999
|
-
isAfterNode = container.nodeType == 1 && offset === container.childNodes.length;
|
12000
|
-
nonEmptyElementsMap = dom.schema.getNonEmptyElements();
|
12001
|
-
directionLeft = start;
|
12002
|
-
|
12003
|
-
if (container.nodeType == 1 && offset > container.childNodes.length - 1) {
|
12004
|
-
directionLeft = false;
|
12005
|
-
}
|
12006
12474
|
|
12007
|
-
|
12008
|
-
|
12009
|
-
|
12010
|
-
offset = 0;
|
12011
|
-
}
|
12012
|
-
|
12013
|
-
// If the container is body try move it into the closest text node or position
|
12014
|
-
if (container === body) {
|
12015
|
-
// If start is before/after a image, table etc
|
12016
|
-
if (directionLeft) {
|
12017
|
-
node = container.childNodes[offset > 0 ? offset - 1 : 0];
|
12018
|
-
if (node) {
|
12019
|
-
if (nonEmptyElementsMap[node.nodeName] || node.nodeName == "TABLE") {
|
12020
|
-
return;
|
12021
|
-
}
|
12022
|
-
}
|
12475
|
+
// Move element offset to best suitable location
|
12476
|
+
if (node.nodeType === 1) {
|
12477
|
+
offset = Math.min(point[0], node.childNodes.length);
|
12023
12478
|
}
|
12024
12479
|
|
12025
|
-
//
|
12026
|
-
if (
|
12027
|
-
|
12028
|
-
|
12029
|
-
offset
|
12030
|
-
|
12031
|
-
|
12032
|
-
if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) {
|
12033
|
-
// Walk the DOM to find a text node to place the caret at or a BR
|
12034
|
-
node = container;
|
12035
|
-
walker = new TreeWalker(container, body);
|
12036
|
-
|
12037
|
-
do {
|
12038
|
-
// Found a text node use that position
|
12039
|
-
if (node.nodeType === 3 && node.nodeValue.length > 0) {
|
12040
|
-
offset = directionLeft ? 0 : node.nodeValue.length;
|
12041
|
-
container = node;
|
12042
|
-
normalized = true;
|
12043
|
-
break;
|
12044
|
-
}
|
12480
|
+
// Set offset within container node
|
12481
|
+
if (start) {
|
12482
|
+
rng.setStart(node, offset);
|
12483
|
+
} else {
|
12484
|
+
rng.setEnd(node, offset);
|
12485
|
+
}
|
12486
|
+
}
|
12045
12487
|
|
12046
|
-
|
12047
|
-
|
12048
|
-
offset = dom.nodeIndex(node);
|
12049
|
-
container = node.parentNode;
|
12488
|
+
return true;
|
12489
|
+
}
|
12050
12490
|
|
12051
|
-
|
12052
|
-
|
12053
|
-
offset++;
|
12054
|
-
}
|
12491
|
+
function restoreEndPoint(suffix) {
|
12492
|
+
var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
|
12055
12493
|
|
12056
|
-
|
12057
|
-
|
12058
|
-
|
12059
|
-
|
12494
|
+
if (marker) {
|
12495
|
+
node = marker.parentNode;
|
12496
|
+
|
12497
|
+
if (suffix == 'start') {
|
12498
|
+
if (!keep) {
|
12499
|
+
idx = dom.nodeIndex(marker);
|
12500
|
+
} else {
|
12501
|
+
node = marker.firstChild;
|
12502
|
+
idx = 1;
|
12060
12503
|
}
|
12061
|
-
}
|
12062
|
-
}
|
12063
12504
|
|
12064
|
-
|
12065
|
-
|
12066
|
-
|
12067
|
-
|
12068
|
-
|
12069
|
-
|
12070
|
-
|
12505
|
+
startContainer = endContainer = node;
|
12506
|
+
startOffset = endOffset = idx;
|
12507
|
+
} else {
|
12508
|
+
if (!keep) {
|
12509
|
+
idx = dom.nodeIndex(marker);
|
12510
|
+
} else {
|
12511
|
+
node = marker.firstChild;
|
12512
|
+
idx = 1;
|
12513
|
+
}
|
12514
|
+
|
12515
|
+
endContainer = node;
|
12516
|
+
endOffset = idx;
|
12071
12517
|
}
|
12072
12518
|
|
12073
|
-
|
12074
|
-
|
12075
|
-
|
12076
|
-
// Seems that only gecko has issues with this.
|
12077
|
-
// Special edge case for <p><a>x</a>|<br></p> since we don't want <p><a>x|</a><br></p>
|
12078
|
-
if (container.nodeType === 1) {
|
12079
|
-
node = container.childNodes[offset];
|
12519
|
+
if (!keep) {
|
12520
|
+
prev = marker.previousSibling;
|
12521
|
+
next = marker.nextSibling;
|
12080
12522
|
|
12081
|
-
//
|
12082
|
-
|
12083
|
-
|
12084
|
-
|
12523
|
+
// Remove all marker text nodes
|
12524
|
+
Tools.each(Tools.grep(marker.childNodes), function(node) {
|
12525
|
+
if (node.nodeType == 3) {
|
12526
|
+
node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
|
12527
|
+
}
|
12528
|
+
});
|
12529
|
+
|
12530
|
+
// Remove marker but keep children if for example contents where inserted into the marker
|
12531
|
+
// Also remove duplicated instances of the marker for example by a
|
12532
|
+
// split operation or by WebKit auto split on paste feature
|
12533
|
+
while ((marker = dom.get(bookmark.id + '_' + suffix))) {
|
12534
|
+
dom.remove(marker, 1);
|
12085
12535
|
}
|
12086
12536
|
|
12087
|
-
|
12088
|
-
|
12089
|
-
|
12537
|
+
// If siblings are text nodes then merge them unless it's Opera since it some how removes the node
|
12538
|
+
// and we are sniffing since adding a lot of detection code for a browser with 3% of the market
|
12539
|
+
// isn't worth the effort. Sorry, Opera but it's just a fact
|
12540
|
+
if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
|
12541
|
+
idx = prev.nodeValue.length;
|
12542
|
+
prev.appendData(next.nodeValue);
|
12543
|
+
dom.remove(next);
|
12544
|
+
|
12545
|
+
if (suffix == 'start') {
|
12546
|
+
startContainer = endContainer = prev;
|
12547
|
+
startOffset = endOffset = idx;
|
12548
|
+
} else {
|
12549
|
+
endContainer = prev;
|
12550
|
+
endOffset = idx;
|
12551
|
+
}
|
12090
12552
|
}
|
12091
12553
|
}
|
12092
12554
|
}
|
12555
|
+
}
|
12093
12556
|
|
12094
|
-
|
12095
|
-
//
|
12096
|
-
|
12097
|
-
|
12098
|
-
findTextNodeRelative(false);
|
12557
|
+
function addBogus(node) {
|
12558
|
+
// Adds a bogus BR element for empty block elements
|
12559
|
+
if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
|
12560
|
+
node.innerHTML = '<br data-mce-bogus="1" />';
|
12099
12561
|
}
|
12100
12562
|
|
12101
|
-
|
12102
|
-
if (normalized) {
|
12103
|
-
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
12104
|
-
}
|
12563
|
+
return node;
|
12105
12564
|
}
|
12106
12565
|
|
12107
|
-
|
12566
|
+
if (bookmark) {
|
12567
|
+
if (bookmark.start) {
|
12568
|
+
rng = dom.createRng();
|
12569
|
+
root = dom.getRoot();
|
12108
12570
|
|
12109
|
-
|
12571
|
+
if (selection.tridentSel) {
|
12572
|
+
return selection.tridentSel.moveToBookmark(bookmark);
|
12573
|
+
}
|
12110
12574
|
|
12111
|
-
|
12112
|
-
|
12113
|
-
|
12575
|
+
if (setEndPoint(true) && setEndPoint()) {
|
12576
|
+
selection.setRng(rng);
|
12577
|
+
}
|
12578
|
+
} else if (bookmark.id) {
|
12579
|
+
// Restore start/end points
|
12580
|
+
restoreEndPoint('start');
|
12581
|
+
restoreEndPoint('end');
|
12114
12582
|
|
12115
|
-
|
12116
|
-
|
12117
|
-
|
12583
|
+
if (startContainer) {
|
12584
|
+
rng = dom.createRng();
|
12585
|
+
rng.setStart(addBogus(startContainer), startOffset);
|
12586
|
+
rng.setEnd(addBogus(endContainer), endOffset);
|
12587
|
+
selection.setRng(rng);
|
12588
|
+
}
|
12589
|
+
} else if (bookmark.name) {
|
12590
|
+
selection.select(dom.select(bookmark.name)[bookmark.index]);
|
12591
|
+
} else if (bookmark.rng) {
|
12592
|
+
selection.setRng(bookmark.rng);
|
12593
|
+
}
|
12118
12594
|
}
|
12119
|
-
|
12120
|
-
return normalized;
|
12121
12595
|
};
|
12122
12596
|
}
|
12123
12597
|
|
12124
12598
|
/**
|
12125
|
-
*
|
12599
|
+
* Returns true/false if the specified node is a bookmark node or not.
|
12126
12600
|
*
|
12127
12601
|
* @static
|
12128
|
-
* @method
|
12129
|
-
* @param {
|
12130
|
-
* @
|
12131
|
-
* @return {Boolean} true/false if the ranges are equal.
|
12602
|
+
* @method isBookmarkNode
|
12603
|
+
* @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
|
12604
|
+
* @return {Boolean} true/false if the node is a bookmark node or not.
|
12132
12605
|
*/
|
12133
|
-
|
12134
|
-
|
12135
|
-
// Compare native IE ranges
|
12136
|
-
if (rng1.item || rng1.duplicate) {
|
12137
|
-
// Both are control ranges and the selected element matches
|
12138
|
-
if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) {
|
12139
|
-
return true;
|
12140
|
-
}
|
12141
|
-
|
12142
|
-
// Both are text ranges and the range matches
|
12143
|
-
if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) {
|
12144
|
-
return true;
|
12145
|
-
}
|
12146
|
-
} else {
|
12147
|
-
// Compare w3c ranges
|
12148
|
-
return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset;
|
12149
|
-
}
|
12150
|
-
}
|
12151
|
-
|
12152
|
-
return false;
|
12606
|
+
BookmarkManager.isBookmarkNode = function(node) {
|
12607
|
+
return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
|
12153
12608
|
};
|
12154
12609
|
|
12155
|
-
return
|
12156
|
-
});
|
12157
|
-
|
12158
|
-
// Included from: js/tinymce/classes/dom/BookmarkManager.js
|
12159
|
-
|
12160
|
-
/**
|
12161
|
-
* BookmarkManager.js
|
12162
|
-
*
|
12163
|
-
* Copyright, Moxiecode Systems AB
|
12164
|
-
* Released under LGPL License.
|
12165
|
-
*
|
12166
|
-
* License: http://www.tinymce.com/license
|
12167
|
-
* Contributing: http://www.tinymce.com/contributing
|
12168
|
-
*/
|
12169
|
-
|
12170
|
-
/**
|
12171
|
-
* This class handles selection bookmarks.
|
12172
|
-
*
|
12173
|
-
* @class tinymce.dom.BookmarkManager
|
12174
|
-
*/
|
12175
|
-
define("tinymce/dom/BookmarkManager", [
|
12176
|
-
"tinymce/Env",
|
12177
|
-
"tinymce/util/Tools"
|
12178
|
-
], function(Env, Tools) {
|
12179
|
-
/**
|
12180
|
-
* Constructs a new BookmarkManager instance for a specific selection instance.
|
12181
|
-
*
|
12182
|
-
* @constructor
|
12183
|
-
* @method BookmarkManager
|
12184
|
-
* @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
|
12185
|
-
*/
|
12186
|
-
function BookmarkManager(selection) {
|
12187
|
-
var dom = selection.dom;
|
12188
|
-
|
12189
|
-
/**
|
12190
|
-
* Returns a bookmark location for the current selection. This bookmark object
|
12191
|
-
* can then be used to restore the selection after some content modification to the document.
|
12192
|
-
*
|
12193
|
-
* @method getBookmark
|
12194
|
-
* @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
|
12195
|
-
* @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
|
12196
|
-
* @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
|
12197
|
-
* @example
|
12198
|
-
* // Stores a bookmark of the current selection
|
12199
|
-
* var bm = tinymce.activeEditor.selection.getBookmark();
|
12200
|
-
*
|
12201
|
-
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
12202
|
-
*
|
12203
|
-
* // Restore the selection bookmark
|
12204
|
-
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
12205
|
-
*/
|
12206
|
-
this.getBookmark = function(type, normalized) {
|
12207
|
-
var rng, rng2, id, collapsed, name, element, chr = '', styles;
|
12208
|
-
|
12209
|
-
function findIndex(name, element) {
|
12210
|
-
var index = 0;
|
12211
|
-
|
12212
|
-
Tools.each(dom.select(name), function(node, i) {
|
12213
|
-
if (node == element) {
|
12214
|
-
index = i;
|
12215
|
-
}
|
12216
|
-
});
|
12217
|
-
|
12218
|
-
return index;
|
12219
|
-
}
|
12220
|
-
|
12221
|
-
function normalizeTableCellSelection(rng) {
|
12222
|
-
function moveEndPoint(start) {
|
12223
|
-
var container, offset, childNodes, prefix = start ? 'start' : 'end';
|
12224
|
-
|
12225
|
-
container = rng[prefix + 'Container'];
|
12226
|
-
offset = rng[prefix + 'Offset'];
|
12227
|
-
|
12228
|
-
if (container.nodeType == 1 && container.nodeName == "TR") {
|
12229
|
-
childNodes = container.childNodes;
|
12230
|
-
container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
|
12231
|
-
if (container) {
|
12232
|
-
offset = start ? 0 : container.childNodes.length;
|
12233
|
-
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
12234
|
-
}
|
12235
|
-
}
|
12236
|
-
}
|
12237
|
-
|
12238
|
-
moveEndPoint(true);
|
12239
|
-
moveEndPoint();
|
12240
|
-
|
12241
|
-
return rng;
|
12242
|
-
}
|
12243
|
-
|
12244
|
-
function getLocation() {
|
12245
|
-
var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
|
12246
|
-
|
12247
|
-
function getPoint(rng, start) {
|
12248
|
-
var container = rng[start ? 'startContainer' : 'endContainer'],
|
12249
|
-
offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
|
12250
|
-
|
12251
|
-
if (container.nodeType == 3) {
|
12252
|
-
if (normalized) {
|
12253
|
-
for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
|
12254
|
-
offset += node.nodeValue.length;
|
12255
|
-
}
|
12256
|
-
}
|
12257
|
-
|
12258
|
-
point.push(offset);
|
12259
|
-
} else {
|
12260
|
-
childNodes = container.childNodes;
|
12261
|
-
|
12262
|
-
if (offset >= childNodes.length && childNodes.length) {
|
12263
|
-
after = 1;
|
12264
|
-
offset = Math.max(0, childNodes.length - 1);
|
12265
|
-
}
|
12266
|
-
|
12267
|
-
point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
|
12268
|
-
}
|
12269
|
-
|
12270
|
-
for (; container && container != root; container = container.parentNode) {
|
12271
|
-
point.push(dom.nodeIndex(container, normalized));
|
12272
|
-
}
|
12273
|
-
|
12274
|
-
return point;
|
12275
|
-
}
|
12276
|
-
|
12277
|
-
bookmark.start = getPoint(rng, true);
|
12278
|
-
|
12279
|
-
if (!selection.isCollapsed()) {
|
12280
|
-
bookmark.end = getPoint(rng);
|
12281
|
-
}
|
12282
|
-
|
12283
|
-
return bookmark;
|
12284
|
-
}
|
12285
|
-
|
12286
|
-
if (type == 2) {
|
12287
|
-
element = selection.getNode();
|
12288
|
-
name = element ? element.nodeName : null;
|
12289
|
-
|
12290
|
-
if (name == 'IMG') {
|
12291
|
-
return {name: name, index: findIndex(name, element)};
|
12292
|
-
}
|
12293
|
-
|
12294
|
-
if (selection.tridentSel) {
|
12295
|
-
return selection.tridentSel.getBookmark(type);
|
12296
|
-
}
|
12297
|
-
|
12298
|
-
return getLocation();
|
12299
|
-
}
|
12300
|
-
|
12301
|
-
// Handle simple range
|
12302
|
-
if (type) {
|
12303
|
-
return {rng: selection.getRng()};
|
12304
|
-
}
|
12305
|
-
|
12306
|
-
rng = selection.getRng();
|
12307
|
-
id = dom.uniqueId();
|
12308
|
-
collapsed = selection.isCollapsed();
|
12309
|
-
styles = 'overflow:hidden;line-height:0px';
|
12310
|
-
|
12311
|
-
// Explorer method
|
12312
|
-
if (rng.duplicate || rng.item) {
|
12313
|
-
// Text selection
|
12314
|
-
if (!rng.item) {
|
12315
|
-
rng2 = rng.duplicate();
|
12316
|
-
|
12317
|
-
try {
|
12318
|
-
// Insert start marker
|
12319
|
-
rng.collapse();
|
12320
|
-
rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
|
12321
|
-
|
12322
|
-
// Insert end marker
|
12323
|
-
if (!collapsed) {
|
12324
|
-
rng2.collapse(false);
|
12325
|
-
|
12326
|
-
// Detect the empty space after block elements in IE and move the
|
12327
|
-
// end back one character <p></p>] becomes <p>]</p>
|
12328
|
-
rng.moveToElementText(rng2.parentElement());
|
12329
|
-
if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
|
12330
|
-
rng2.move('character', -1);
|
12331
|
-
}
|
12332
|
-
|
12333
|
-
rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
|
12334
|
-
}
|
12335
|
-
} catch (ex) {
|
12336
|
-
// IE might throw unspecified error so lets ignore it
|
12337
|
-
return null;
|
12338
|
-
}
|
12339
|
-
} else {
|
12340
|
-
// Control selection
|
12341
|
-
element = rng.item(0);
|
12342
|
-
name = element.nodeName;
|
12343
|
-
|
12344
|
-
return {name: name, index: findIndex(name, element)};
|
12345
|
-
}
|
12346
|
-
} else {
|
12347
|
-
element = selection.getNode();
|
12348
|
-
name = element.nodeName;
|
12349
|
-
if (name == 'IMG') {
|
12350
|
-
return {name: name, index: findIndex(name, element)};
|
12351
|
-
}
|
12352
|
-
|
12353
|
-
// W3C method
|
12354
|
-
rng2 = normalizeTableCellSelection(rng.cloneRange());
|
12355
|
-
|
12356
|
-
// Insert end marker
|
12357
|
-
if (!collapsed) {
|
12358
|
-
rng2.collapse(false);
|
12359
|
-
rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
|
12360
|
-
}
|
12361
|
-
|
12362
|
-
rng = normalizeTableCellSelection(rng);
|
12363
|
-
rng.collapse(true);
|
12364
|
-
rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
|
12365
|
-
}
|
12366
|
-
|
12367
|
-
selection.moveToBookmark({id: id, keep: 1});
|
12368
|
-
|
12369
|
-
return {id: id};
|
12370
|
-
};
|
12371
|
-
|
12372
|
-
/**
|
12373
|
-
* Restores the selection to the specified bookmark.
|
12374
|
-
*
|
12375
|
-
* @method moveToBookmark
|
12376
|
-
* @param {Object} bookmark Bookmark to restore selection from.
|
12377
|
-
* @return {Boolean} true/false if it was successful or not.
|
12378
|
-
* @example
|
12379
|
-
* // Stores a bookmark of the current selection
|
12380
|
-
* var bm = tinymce.activeEditor.selection.getBookmark();
|
12381
|
-
*
|
12382
|
-
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
12383
|
-
*
|
12384
|
-
* // Restore the selection bookmark
|
12385
|
-
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
12386
|
-
*/
|
12387
|
-
this.moveToBookmark = function(bookmark) {
|
12388
|
-
var rng, root, startContainer, endContainer, startOffset, endOffset;
|
12389
|
-
|
12390
|
-
function setEndPoint(start) {
|
12391
|
-
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
|
12392
|
-
|
12393
|
-
if (point) {
|
12394
|
-
offset = point[0];
|
12395
|
-
|
12396
|
-
// Find container node
|
12397
|
-
for (node = root, i = point.length - 1; i >= 1; i--) {
|
12398
|
-
children = node.childNodes;
|
12399
|
-
|
12400
|
-
if (point[i] > children.length - 1) {
|
12401
|
-
return;
|
12402
|
-
}
|
12403
|
-
|
12404
|
-
node = children[point[i]];
|
12405
|
-
}
|
12406
|
-
|
12407
|
-
// Move text offset to best suitable location
|
12408
|
-
if (node.nodeType === 3) {
|
12409
|
-
offset = Math.min(point[0], node.nodeValue.length);
|
12410
|
-
}
|
12411
|
-
|
12412
|
-
// Move element offset to best suitable location
|
12413
|
-
if (node.nodeType === 1) {
|
12414
|
-
offset = Math.min(point[0], node.childNodes.length);
|
12415
|
-
}
|
12416
|
-
|
12417
|
-
// Set offset within container node
|
12418
|
-
if (start) {
|
12419
|
-
rng.setStart(node, offset);
|
12420
|
-
} else {
|
12421
|
-
rng.setEnd(node, offset);
|
12422
|
-
}
|
12423
|
-
}
|
12424
|
-
|
12425
|
-
return true;
|
12426
|
-
}
|
12427
|
-
|
12428
|
-
function restoreEndPoint(suffix) {
|
12429
|
-
var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
|
12430
|
-
|
12431
|
-
if (marker) {
|
12432
|
-
node = marker.parentNode;
|
12433
|
-
|
12434
|
-
if (suffix == 'start') {
|
12435
|
-
if (!keep) {
|
12436
|
-
idx = dom.nodeIndex(marker);
|
12437
|
-
} else {
|
12438
|
-
node = marker.firstChild;
|
12439
|
-
idx = 1;
|
12440
|
-
}
|
12441
|
-
|
12442
|
-
startContainer = endContainer = node;
|
12443
|
-
startOffset = endOffset = idx;
|
12444
|
-
} else {
|
12445
|
-
if (!keep) {
|
12446
|
-
idx = dom.nodeIndex(marker);
|
12447
|
-
} else {
|
12448
|
-
node = marker.firstChild;
|
12449
|
-
idx = 1;
|
12450
|
-
}
|
12451
|
-
|
12452
|
-
endContainer = node;
|
12453
|
-
endOffset = idx;
|
12454
|
-
}
|
12455
|
-
|
12456
|
-
if (!keep) {
|
12457
|
-
prev = marker.previousSibling;
|
12458
|
-
next = marker.nextSibling;
|
12459
|
-
|
12460
|
-
// Remove all marker text nodes
|
12461
|
-
Tools.each(Tools.grep(marker.childNodes), function(node) {
|
12462
|
-
if (node.nodeType == 3) {
|
12463
|
-
node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
|
12464
|
-
}
|
12465
|
-
});
|
12466
|
-
|
12467
|
-
// Remove marker but keep children if for example contents where inserted into the marker
|
12468
|
-
// Also remove duplicated instances of the marker for example by a
|
12469
|
-
// split operation or by WebKit auto split on paste feature
|
12470
|
-
while ((marker = dom.get(bookmark.id + '_' + suffix))) {
|
12471
|
-
dom.remove(marker, 1);
|
12472
|
-
}
|
12473
|
-
|
12474
|
-
// If siblings are text nodes then merge them unless it's Opera since it some how removes the node
|
12475
|
-
// and we are sniffing since adding a lot of detection code for a browser with 3% of the market
|
12476
|
-
// isn't worth the effort. Sorry, Opera but it's just a fact
|
12477
|
-
if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
|
12478
|
-
idx = prev.nodeValue.length;
|
12479
|
-
prev.appendData(next.nodeValue);
|
12480
|
-
dom.remove(next);
|
12481
|
-
|
12482
|
-
if (suffix == 'start') {
|
12483
|
-
startContainer = endContainer = prev;
|
12484
|
-
startOffset = endOffset = idx;
|
12485
|
-
} else {
|
12486
|
-
endContainer = prev;
|
12487
|
-
endOffset = idx;
|
12488
|
-
}
|
12489
|
-
}
|
12490
|
-
}
|
12491
|
-
}
|
12492
|
-
}
|
12493
|
-
|
12494
|
-
function addBogus(node) {
|
12495
|
-
// Adds a bogus BR element for empty block elements
|
12496
|
-
if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
|
12497
|
-
node.innerHTML = '<br data-mce-bogus="1" />';
|
12498
|
-
}
|
12499
|
-
|
12500
|
-
return node;
|
12501
|
-
}
|
12502
|
-
|
12503
|
-
if (bookmark) {
|
12504
|
-
if (bookmark.start) {
|
12505
|
-
rng = dom.createRng();
|
12506
|
-
root = dom.getRoot();
|
12507
|
-
|
12508
|
-
if (selection.tridentSel) {
|
12509
|
-
return selection.tridentSel.moveToBookmark(bookmark);
|
12510
|
-
}
|
12511
|
-
|
12512
|
-
if (setEndPoint(true) && setEndPoint()) {
|
12513
|
-
selection.setRng(rng);
|
12514
|
-
}
|
12515
|
-
} else if (bookmark.id) {
|
12516
|
-
// Restore start/end points
|
12517
|
-
restoreEndPoint('start');
|
12518
|
-
restoreEndPoint('end');
|
12519
|
-
|
12520
|
-
if (startContainer) {
|
12521
|
-
rng = dom.createRng();
|
12522
|
-
rng.setStart(addBogus(startContainer), startOffset);
|
12523
|
-
rng.setEnd(addBogus(endContainer), endOffset);
|
12524
|
-
selection.setRng(rng);
|
12525
|
-
}
|
12526
|
-
} else if (bookmark.name) {
|
12527
|
-
selection.select(dom.select(bookmark.name)[bookmark.index]);
|
12528
|
-
} else if (bookmark.rng) {
|
12529
|
-
selection.setRng(bookmark.rng);
|
12530
|
-
}
|
12531
|
-
}
|
12532
|
-
};
|
12533
|
-
}
|
12534
|
-
|
12535
|
-
/**
|
12536
|
-
* Returns true/false if the specified node is a bookmark node or not.
|
12537
|
-
*
|
12538
|
-
* @static
|
12539
|
-
* @method isBookmarkNode
|
12540
|
-
* @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
|
12541
|
-
* @return {Boolean} true/false if the node is a bookmark node or not.
|
12542
|
-
*/
|
12543
|
-
BookmarkManager.isBookmarkNode = function(node) {
|
12544
|
-
return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
|
12545
|
-
};
|
12546
|
-
|
12547
|
-
return BookmarkManager;
|
12610
|
+
return BookmarkManager;
|
12548
12611
|
});
|
12549
12612
|
|
12550
12613
|
// Included from: js/tinymce/classes/dom/Selection.js
|
@@ -12981,9 +13044,9 @@ define("tinymce/dom/Selection", [
|
|
12981
13044
|
* Collapse the selection to start or end of range.
|
12982
13045
|
*
|
12983
13046
|
* @method collapse
|
12984
|
-
* @param {Boolean}
|
13047
|
+
* @param {Boolean} toStart Optional boolean state if to collapse to end or not. Defaults to start.
|
12985
13048
|
*/
|
12986
|
-
collapse: function(
|
13049
|
+
collapse: function(toStart) {
|
12987
13050
|
var self = this, rng = self.getRng(), node;
|
12988
13051
|
|
12989
13052
|
// Control range on IE
|
@@ -12993,7 +13056,7 @@ define("tinymce/dom/Selection", [
|
|
12993
13056
|
rng.moveToElementText(node);
|
12994
13057
|
}
|
12995
13058
|
|
12996
|
-
rng.collapse(!!
|
13059
|
+
rng.collapse(!!toStart);
|
12997
13060
|
self.setRng(rng);
|
12998
13061
|
},
|
12999
13062
|
|
@@ -14138,62 +14201,6 @@ define("tinymce/Formatter", [
|
|
14138
14201
|
return rng;
|
14139
14202
|
}
|
14140
14203
|
|
14141
|
-
function applyStyleToList(node, bookmark, wrapElm, newWrappers, process) {
|
14142
|
-
var nodes = [], listIndex = -1, list, startIndex = -1, endIndex = -1, currentWrapElm;
|
14143
|
-
|
14144
|
-
// find the index of the first child list.
|
14145
|
-
each(node.childNodes, function(n, index) {
|
14146
|
-
if (n.nodeName === "UL" || n.nodeName === "OL") {
|
14147
|
-
listIndex = index;
|
14148
|
-
list = n;
|
14149
|
-
return false;
|
14150
|
-
}
|
14151
|
-
});
|
14152
|
-
|
14153
|
-
// get the index of the bookmarks
|
14154
|
-
each(node.childNodes, function(n, index) {
|
14155
|
-
if (isBookmarkNode(n)) {
|
14156
|
-
if (n.id == bookmark.id + "_start") {
|
14157
|
-
startIndex = index;
|
14158
|
-
} else if (n.id == bookmark.id + "_end") {
|
14159
|
-
endIndex = index;
|
14160
|
-
}
|
14161
|
-
}
|
14162
|
-
});
|
14163
|
-
|
14164
|
-
// if the selection spans across an embedded list, or there isn't an embedded list - handle processing normally
|
14165
|
-
if (listIndex <= 0 || (startIndex < listIndex && endIndex > listIndex)) {
|
14166
|
-
each(grep(node.childNodes), process);
|
14167
|
-
return 0;
|
14168
|
-
} else {
|
14169
|
-
currentWrapElm = dom.clone(wrapElm, FALSE);
|
14170
|
-
|
14171
|
-
// create a list of the nodes on the same side of the list as the selection
|
14172
|
-
each(grep(node.childNodes), function(n, index) {
|
14173
|
-
if ((startIndex < listIndex && index < listIndex) || (startIndex > listIndex && index > listIndex)) {
|
14174
|
-
nodes.push(n);
|
14175
|
-
n.parentNode.removeChild(n);
|
14176
|
-
}
|
14177
|
-
});
|
14178
|
-
|
14179
|
-
// insert the wrapping element either before or after the list.
|
14180
|
-
if (startIndex < listIndex) {
|
14181
|
-
node.insertBefore(currentWrapElm, list);
|
14182
|
-
} else if (startIndex > listIndex) {
|
14183
|
-
node.insertBefore(currentWrapElm, list.nextSibling);
|
14184
|
-
}
|
14185
|
-
|
14186
|
-
// add the new nodes to the list.
|
14187
|
-
newWrappers.push(currentWrapElm);
|
14188
|
-
|
14189
|
-
each(nodes, function(node) {
|
14190
|
-
currentWrapElm.appendChild(node);
|
14191
|
-
});
|
14192
|
-
|
14193
|
-
return currentWrapElm;
|
14194
|
-
}
|
14195
|
-
}
|
14196
|
-
|
14197
14204
|
function applyRngStyle(rng, bookmark, node_specific) {
|
14198
14205
|
var newWrappers = [], wrapName, wrapElm, contentEditable = true;
|
14199
14206
|
|
@@ -14290,10 +14297,6 @@ define("tinymce/Formatter", [
|
|
14290
14297
|
}
|
14291
14298
|
|
14292
14299
|
currentWrapElm.appendChild(node);
|
14293
|
-
} else if (nodeName == 'li' && bookmark) {
|
14294
|
-
// Start wrapping - if we are in a list node and have a bookmark, then
|
14295
|
-
// we will always begin by wrapping in a new element.
|
14296
|
-
currentWrapElm = applyStyleToList(node, bookmark, wrapElm, newWrappers, process);
|
14297
14300
|
} else {
|
14298
14301
|
// Start a new wrapper for possible children
|
14299
14302
|
currentWrapElm = 0;
|
@@ -14558,12 +14561,12 @@ define("tinymce/Formatter", [
|
|
14558
14561
|
return formatRoot;
|
14559
14562
|
}
|
14560
14563
|
|
14561
|
-
function wrapAndSplit(
|
14564
|
+
function wrapAndSplit(formatRoot, container, target, split) {
|
14562
14565
|
var parent, clone, lastClone, firstClone, i, formatRootParent;
|
14563
14566
|
|
14564
14567
|
// Format root found then clone formats and split it
|
14565
|
-
if (
|
14566
|
-
formatRootParent =
|
14568
|
+
if (formatRoot) {
|
14569
|
+
formatRootParent = formatRoot.parentNode;
|
14567
14570
|
|
14568
14571
|
for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) {
|
14569
14572
|
clone = dom.clone(parent, FALSE);
|
@@ -14590,8 +14593,8 @@ define("tinymce/Formatter", [
|
|
14590
14593
|
}
|
14591
14594
|
|
14592
14595
|
// Never split block elements if the format is mixed
|
14593
|
-
if (split && (!format.mixed || !isBlock(
|
14594
|
-
container = dom.split(
|
14596
|
+
if (split && (!format.mixed || !isBlock(formatRoot))) {
|
14597
|
+
container = dom.split(formatRoot, container);
|
14595
14598
|
}
|
14596
14599
|
|
14597
14600
|
// Wrap container in cloned formats
|
@@ -14955,6 +14958,11 @@ define("tinymce/Formatter", [
|
|
14955
14958
|
ed.on('NodeChange', function(e) {
|
14956
14959
|
var parents = getParents(e.element), matchedFormats = {};
|
14957
14960
|
|
14961
|
+
// Ignore bogus nodes like the <a> tag created by moveStart()
|
14962
|
+
parents = Tools.grep(parents, function(node) {
|
14963
|
+
return !node.getAttribute('data-mce-bogus');
|
14964
|
+
});
|
14965
|
+
|
14958
14966
|
// Check for new formats
|
14959
14967
|
each(formatChangeData, function(callbacks, format) {
|
14960
14968
|
each(parents, function(node) {
|
@@ -16139,7 +16147,7 @@ define("tinymce/Formatter", [
|
|
16139
16147
|
if (node.nodeType == 3 && !isWhiteSpaceNode(node)) {
|
16140
16148
|
// IE has a "neat" feature where it moves the start node into the closest element
|
16141
16149
|
// we can avoid this by inserting an element before it and then remove it after we set the selection
|
16142
|
-
tmpNode = dom.create('a',
|
16150
|
+
tmpNode = dom.create('a', {'data-mce-bogus': 'all'}, INVISIBLE_CHAR);
|
16143
16151
|
node.parentNode.insertBefore(tmpNode, node);
|
16144
16152
|
|
16145
16153
|
// Set selection and remove tmpNode
|
@@ -16325,38 +16333,6 @@ define("tinymce/UndoManager", [
|
|
16325
16333
|
}
|
16326
16334
|
});
|
16327
16335
|
|
16328
|
-
// Selection range isn't updated until after the click events default handler is executed
|
16329
|
-
// so we need to wait for the selection to update on Gecko/WebKit it happens right away.
|
16330
|
-
// On IE it might take a while so we listen for the SelectionChange event.
|
16331
|
-
//
|
16332
|
-
// We can't use the SelectionChange on all browsers event since Gecko doesn't support that.
|
16333
|
-
if (Env.ie) {
|
16334
|
-
editor.on('MouseUp', function(e) {
|
16335
|
-
if (!e.isDefaultPrevented()) {
|
16336
|
-
editor.once('SelectionChange', function() {
|
16337
|
-
// Selection change might fire when focus is lost
|
16338
|
-
if (editor.dom.isChildOf(editor.selection.getStart(), editor.getBody())) {
|
16339
|
-
editor.nodeChanged();
|
16340
|
-
}
|
16341
|
-
});
|
16342
|
-
|
16343
|
-
editor.nodeChanged();
|
16344
|
-
}
|
16345
|
-
});
|
16346
|
-
} else {
|
16347
|
-
editor.on('MouseUp', function() {
|
16348
|
-
editor.nodeChanged();
|
16349
|
-
});
|
16350
|
-
|
16351
|
-
editor.on('Click', function(e) {
|
16352
|
-
if (!e.isDefaultPrevented()) {
|
16353
|
-
setTimeout(function() {
|
16354
|
-
editor.nodeChanged();
|
16355
|
-
}, 0);
|
16356
|
-
}
|
16357
|
-
});
|
16358
|
-
}
|
16359
|
-
|
16360
16336
|
self = {
|
16361
16337
|
// Explose for debugging reasons
|
16362
16338
|
data: data,
|
@@ -21577,7 +21553,13 @@ define("tinymce/ui/KeyboardNavigation", [
|
|
21577
21553
|
return function(settings) {
|
21578
21554
|
var root = settings.root, focusedElement, focusedControl;
|
21579
21555
|
|
21580
|
-
|
21556
|
+
try {
|
21557
|
+
focusedElement = document.activeElement;
|
21558
|
+
} catch (ex) {
|
21559
|
+
// IE sometimes fails to return a proper element
|
21560
|
+
focusedElement = document.body;
|
21561
|
+
}
|
21562
|
+
|
21581
21563
|
focusedControl = root.getParentCtrl(focusedElement);
|
21582
21564
|
|
21583
21565
|
/**
|
@@ -23953,44 +23935,41 @@ define("tinymce/ui/MessageBox", [
|
|
23953
23935
|
msgBox: function(settings) {
|
23954
23936
|
var buttons, callback = settings.callback || function() {};
|
23955
23937
|
|
23938
|
+
function createButton(text, status, primary) {
|
23939
|
+
return {
|
23940
|
+
type: "button",
|
23941
|
+
text: text,
|
23942
|
+
subtype: primary ? 'primary' : '',
|
23943
|
+
onClick: function(e) {
|
23944
|
+
e.control.parents()[1].close();
|
23945
|
+
callback(status);
|
23946
|
+
}
|
23947
|
+
};
|
23948
|
+
}
|
23949
|
+
|
23956
23950
|
switch (settings.buttons) {
|
23957
23951
|
case MessageBox.OK_CANCEL:
|
23958
23952
|
buttons = [
|
23959
|
-
|
23960
|
-
|
23961
|
-
callback(true);
|
23962
|
-
}},
|
23963
|
-
|
23964
|
-
{type: "button", text: "Cancel", onClick: function(e) {
|
23965
|
-
e.control.parents()[1].close();
|
23966
|
-
callback(false);
|
23967
|
-
}}
|
23953
|
+
createButton('Ok', true, true),
|
23954
|
+
createButton('Cancel', false)
|
23968
23955
|
];
|
23969
23956
|
break;
|
23970
23957
|
|
23971
23958
|
case MessageBox.YES_NO:
|
23972
|
-
buttons = [
|
23973
|
-
{type: "button", text: "Ok", subtype: "primary", onClick: function(e) {
|
23974
|
-
e.control.parents()[1].close();
|
23975
|
-
callback(true);
|
23976
|
-
}}
|
23977
|
-
];
|
23978
|
-
break;
|
23979
|
-
|
23980
23959
|
case MessageBox.YES_NO_CANCEL:
|
23981
23960
|
buttons = [
|
23982
|
-
|
23983
|
-
|
23984
|
-
}}
|
23961
|
+
createButton('Yes', 1, true),
|
23962
|
+
createButton('No', 0)
|
23985
23963
|
];
|
23964
|
+
|
23965
|
+
if (settings.buttons == MessageBox.YES_NO_CANCEL) {
|
23966
|
+
buttons.push(createButton('Cancel', -1));
|
23967
|
+
}
|
23986
23968
|
break;
|
23987
23969
|
|
23988
23970
|
default:
|
23989
23971
|
buttons = [
|
23990
|
-
|
23991
|
-
e.control.parents()[1].close();
|
23992
|
-
callback(true);
|
23993
|
-
}}
|
23972
|
+
createButton('Ok', true, true)
|
23994
23973
|
];
|
23995
23974
|
break;
|
23996
23975
|
}
|
@@ -24802,8 +24781,6 @@ define("tinymce/util/Quirks", [
|
|
24802
24781
|
if (e.nodeName == 'A' && dom.hasClass(e, 'mce-item-anchor')) {
|
24803
24782
|
selection.select(e);
|
24804
24783
|
}
|
24805
|
-
|
24806
|
-
editor.nodeChanged();
|
24807
24784
|
});
|
24808
24785
|
}
|
24809
24786
|
|
@@ -25433,6 +25410,26 @@ define("tinymce/util/Quirks", [
|
|
25433
25410
|
});
|
25434
25411
|
}
|
25435
25412
|
|
25413
|
+
/**
|
25414
|
+
* Sometimes WebKit/Blink generates BR elements with the Apple-interchange-newline class.
|
25415
|
+
*
|
25416
|
+
* Scenario:
|
25417
|
+
* 1) Create a table 2x2.
|
25418
|
+
* 2) Select and copy cells A2-B2.
|
25419
|
+
* 3) Paste and it will add BR element to table cell.
|
25420
|
+
*/
|
25421
|
+
function removeAppleInterchangeBrs() {
|
25422
|
+
parser.addNodeFilter('br', function(nodes) {
|
25423
|
+
var i = nodes.length;
|
25424
|
+
|
25425
|
+
while (i--) {
|
25426
|
+
if (nodes[i].attr('class') == 'Apple-interchange-newline') {
|
25427
|
+
nodes[i].remove();
|
25428
|
+
}
|
25429
|
+
}
|
25430
|
+
});
|
25431
|
+
}
|
25432
|
+
|
25436
25433
|
// All browsers
|
25437
25434
|
removeBlockQuoteOnBackSpace();
|
25438
25435
|
emptyEditorWhenDeleting();
|
@@ -25446,6 +25443,7 @@ define("tinymce/util/Quirks", [
|
|
25446
25443
|
setDefaultBlockType();
|
25447
25444
|
blockFormSubmitInsideEditor();
|
25448
25445
|
disableBackspaceIntoATable();
|
25446
|
+
removeAppleInterchangeBrs();
|
25449
25447
|
|
25450
25448
|
// iOS
|
25451
25449
|
if (Env.iOS) {
|
@@ -25925,6 +25923,7 @@ define("tinymce/Editor", [
|
|
25925
25923
|
"tinymce/dom/DOMUtils",
|
25926
25924
|
"tinymce/dom/DomQuery",
|
25927
25925
|
"tinymce/AddOnManager",
|
25926
|
+
"tinymce/NodeChange",
|
25928
25927
|
"tinymce/html/Node",
|
25929
25928
|
"tinymce/dom/Serializer",
|
25930
25929
|
"tinymce/html/Serializer",
|
@@ -25946,7 +25945,7 @@ define("tinymce/Editor", [
|
|
25946
25945
|
"tinymce/EditorObservable",
|
25947
25946
|
"tinymce/Shortcuts"
|
25948
25947
|
], function(
|
25949
|
-
DOMUtils, DomQuery, AddOnManager, Node, DomSerializer, Serializer,
|
25948
|
+
DOMUtils, DomQuery, AddOnManager, NodeChange, Node, DomSerializer, Serializer,
|
25950
25949
|
Selection, Formatter, UndoManager, EnterKey, ForceBlocks, EditorCommands,
|
25951
25950
|
URI, ScriptLoader, EventUtils, WindowManager,
|
25952
25951
|
Schema, DomParser, Quirks, Env, Tools, EditorObservable, Shortcuts
|
@@ -26018,9 +26017,9 @@ define("tinymce/Editor", [
|
|
26018
26017
|
inline_styles: true,
|
26019
26018
|
convert_fonts_to_spans: true,
|
26020
26019
|
indent: 'simple',
|
26021
|
-
indent_before: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,' +
|
26020
|
+
indent_before: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,ol,li,dl,dt,dd,area,table,thead,' +
|
26022
26021
|
'tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist',
|
26023
|
-
indent_after: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,' +
|
26022
|
+
indent_after: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,ol,li,dl,dt,dd,area,table,thead,' +
|
26024
26023
|
'tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist',
|
26025
26024
|
validate: true,
|
26026
26025
|
entity_encoding: 'named',
|
@@ -26125,6 +26124,10 @@ define("tinymce/Editor", [
|
|
26125
26124
|
self.queryValueCommands = {};
|
26126
26125
|
self.loadedCSS = {};
|
26127
26126
|
|
26127
|
+
if (settings.target) {
|
26128
|
+
self.targetElm = settings.target;
|
26129
|
+
}
|
26130
|
+
|
26128
26131
|
self.suffix = editorManager.suffix;
|
26129
26132
|
self.editorManager = editorManager;
|
26130
26133
|
self.inline = settings.inline;
|
@@ -26434,12 +26437,6 @@ define("tinymce/Editor", [
|
|
26434
26437
|
|
26435
26438
|
// Resize editor
|
26436
26439
|
if (!settings.content_editable) {
|
26437
|
-
DOM.setStyles(o.sizeContainer || o.editorContainer, {
|
26438
|
-
wi2dth: w,
|
26439
|
-
// TODO: Fix this
|
26440
|
-
h2eight: h
|
26441
|
-
});
|
26442
|
-
|
26443
26440
|
h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : '');
|
26444
26441
|
if (h < minHeight) {
|
26445
26442
|
h = minHeight;
|
@@ -26517,8 +26514,9 @@ define("tinymce/Editor", [
|
|
26517
26514
|
bodyClass = bodyClass[self.id] || '';
|
26518
26515
|
}
|
26519
26516
|
|
26520
|
-
self.iframeHTML += '</head><body id="' + bodyId +
|
26521
|
-
'
|
26517
|
+
self.iframeHTML += '</head><body id="' + bodyId +
|
26518
|
+
'" class="mce-content-body ' + bodyClass +
|
26519
|
+
'" data-id="' + self.id + '"><br></body></html>';
|
26522
26520
|
|
26523
26521
|
/*eslint no-script-url:0 */
|
26524
26522
|
var domainRelaxUrl = 'javascript:(function(){' +
|
@@ -26533,14 +26531,14 @@ define("tinymce/Editor", [
|
|
26533
26531
|
|
26534
26532
|
// Create iframe
|
26535
26533
|
// TODO: ACC add the appropriate description on this.
|
26536
|
-
|
26534
|
+
var ifr = DOM.create('iframe', {
|
26537
26535
|
id: self.id + "_ifr",
|
26538
|
-
src: url || 'javascript:""', // Workaround for HTTPS warning in IE6/7
|
26536
|
+
//src: url || 'javascript:""', // Workaround for HTTPS warning in IE6/7
|
26539
26537
|
frameBorder: '0',
|
26540
26538
|
allowTransparency: "true",
|
26541
26539
|
title: self.editorManager.translate(
|
26542
|
-
|
26543
|
-
|
26540
|
+
"Rich Text Area. Press ALT-F9 for menu. " +
|
26541
|
+
"Press ALT-F10 for toolbar. Press ALT-0 for help"
|
26544
26542
|
),
|
26545
26543
|
style: {
|
26546
26544
|
width: '100%',
|
@@ -26549,6 +26547,15 @@ define("tinymce/Editor", [
|
|
26549
26547
|
}
|
26550
26548
|
});
|
26551
26549
|
|
26550
|
+
ifr.onload = function() {
|
26551
|
+
ifr.onload = null;
|
26552
|
+
self.fire("load");
|
26553
|
+
};
|
26554
|
+
|
26555
|
+
DOM.setAttrib("src", url || 'javascript:""');
|
26556
|
+
|
26557
|
+
n = DOM.add(o.iframeContainer, ifr);
|
26558
|
+
|
26552
26559
|
// Try accessing the document this will fail on IE when document.domain is set to the same as location.hostname
|
26553
26560
|
// Then we have to force domain relaxing using the domainRelaxUrl approach very ugly!!
|
26554
26561
|
if (ie) {
|
@@ -26560,12 +26567,14 @@ define("tinymce/Editor", [
|
|
26560
26567
|
}
|
26561
26568
|
|
26562
26569
|
self.contentAreaContainer = o.iframeContainer;
|
26570
|
+
self.iframeElement = ifr;
|
26563
26571
|
|
26564
26572
|
if (o.editorContainer) {
|
26565
26573
|
DOM.get(o.editorContainer).style.display = self.orgDisplay;
|
26574
|
+
self.hidden = DOM.isHidden(o.editorContainer);
|
26566
26575
|
}
|
26567
26576
|
|
26568
|
-
|
26577
|
+
self.getElement().style.display = 'none';
|
26569
26578
|
DOM.setAttrib(self.id, 'aria-hidden', true);
|
26570
26579
|
|
26571
26580
|
if (!url) {
|
@@ -26583,7 +26592,7 @@ define("tinymce/Editor", [
|
|
26583
26592
|
* @private
|
26584
26593
|
*/
|
26585
26594
|
initContentBody: function(skipWrite) {
|
26586
|
-
var self = this, settings = self.settings, targetElm =
|
26595
|
+
var self = this, settings = self.settings, targetElm = self.getElement(), doc = self.getDoc(), body, contentCssText;
|
26587
26596
|
|
26588
26597
|
// Restore visibility on target element
|
26589
26598
|
if (!settings.inline) {
|
@@ -26656,7 +26665,7 @@ define("tinymce/Editor", [
|
|
26656
26665
|
hex_colors: settings.force_hex_style_colors,
|
26657
26666
|
class_filter: settings.class_filter,
|
26658
26667
|
update_styles: true,
|
26659
|
-
root_element:
|
26668
|
+
root_element: self.inline ? self.getBody() : null,
|
26660
26669
|
collect: settings.content_editable,
|
26661
26670
|
schema: self.schema,
|
26662
26671
|
onSetAttrib: function(e) {
|
@@ -26730,7 +26739,7 @@ define("tinymce/Editor", [
|
|
26730
26739
|
node = nodes[i];
|
26731
26740
|
|
26732
26741
|
if (node.isEmpty(nonEmptyElements)) {
|
26733
|
-
node.
|
26742
|
+
node.append(new Node('br', 1)).shortEnded = true;
|
26734
26743
|
}
|
26735
26744
|
}
|
26736
26745
|
});
|
@@ -26785,6 +26794,7 @@ define("tinymce/Editor", [
|
|
26785
26794
|
self.forceBlocks = new ForceBlocks(self);
|
26786
26795
|
self.enterKey = new EnterKey(self);
|
26787
26796
|
self.editorCommands = new EditorCommands(self);
|
26797
|
+
self._nodeChangeDispatcher = new NodeChange(self);
|
26788
26798
|
|
26789
26799
|
self.fire('PreInit');
|
26790
26800
|
|
@@ -26795,7 +26805,7 @@ define("tinymce/Editor", [
|
|
26795
26805
|
|
26796
26806
|
self.fire('PostRender');
|
26797
26807
|
|
26798
|
-
self.quirks = Quirks(self);
|
26808
|
+
self.quirks = new Quirks(self);
|
26799
26809
|
|
26800
26810
|
if (settings.directionality) {
|
26801
26811
|
body.dir = settings.directionality;
|
@@ -26887,13 +26897,13 @@ define("tinymce/Editor", [
|
|
26887
26897
|
* it will also place DOM focus inside the editor.
|
26888
26898
|
*
|
26889
26899
|
* @method focus
|
26890
|
-
* @param {Boolean}
|
26900
|
+
* @param {Boolean} skipFocus Skip DOM focus. Just set is as the active editor.
|
26891
26901
|
*/
|
26892
|
-
focus: function(
|
26902
|
+
focus: function(skipFocus) {
|
26893
26903
|
var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, rng;
|
26894
26904
|
var controlElm, doc = self.getDoc(), body;
|
26895
26905
|
|
26896
|
-
if (!
|
26906
|
+
if (!skipFocus) {
|
26897
26907
|
// Get selected control element
|
26898
26908
|
rng = selection.getRng();
|
26899
26909
|
if (rng.item) {
|
@@ -27070,36 +27080,7 @@ define("tinymce/Editor", [
|
|
27070
27080
|
* @param {Object} args Optional args to pass to NodeChange event handlers.
|
27071
27081
|
*/
|
27072
27082
|
nodeChanged: function(args) {
|
27073
|
-
|
27074
|
-
|
27075
|
-
// Fix for bug #1896577 it seems that this can not be fired while the editor is loading
|
27076
|
-
if (self.initialized && !self.settings.disable_nodechange && !self.settings.readonly) {
|
27077
|
-
// Get start node
|
27078
|
-
root = self.getBody();
|
27079
|
-
node = selection.getStart() || root;
|
27080
|
-
node = ie && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state
|
27081
|
-
|
27082
|
-
// Edge case for <p>|<img></p>
|
27083
|
-
if (node.nodeName == 'IMG' && selection.isCollapsed()) {
|
27084
|
-
node = node.parentNode;
|
27085
|
-
}
|
27086
|
-
|
27087
|
-
// Get parents and add them to object
|
27088
|
-
parents = [];
|
27089
|
-
self.dom.getParent(node, function(node) {
|
27090
|
-
if (node === root) {
|
27091
|
-
return true;
|
27092
|
-
}
|
27093
|
-
|
27094
|
-
parents.push(node);
|
27095
|
-
});
|
27096
|
-
|
27097
|
-
args = args || {};
|
27098
|
-
args.element = node;
|
27099
|
-
args.parents = parents;
|
27100
|
-
|
27101
|
-
self.fire('NodeChange', args);
|
27102
|
-
}
|
27083
|
+
this._nodeChangeDispatcher.nodeChanged(args);
|
27103
27084
|
},
|
27104
27085
|
|
27105
27086
|
/**
|
@@ -27645,7 +27626,7 @@ define("tinymce/Editor", [
|
|
27645
27626
|
content = '<br data-mce-bogus="1">';
|
27646
27627
|
}
|
27647
27628
|
|
27648
|
-
body
|
27629
|
+
self.dom.setHTML(body, content);
|
27649
27630
|
|
27650
27631
|
self.fire('SetContent', args);
|
27651
27632
|
} else {
|
@@ -27793,7 +27774,11 @@ define("tinymce/Editor", [
|
|
27793
27774
|
* @return {Element} HTML DOM element for the replaced element.
|
27794
27775
|
*/
|
27795
27776
|
getElement: function() {
|
27796
|
-
|
27777
|
+
if (!this.targetElm) {
|
27778
|
+
this.targetElm = DOM.get(this.id);
|
27779
|
+
}
|
27780
|
+
|
27781
|
+
return this.targetElm;
|
27797
27782
|
},
|
27798
27783
|
|
27799
27784
|
/**
|
@@ -27806,7 +27791,7 @@ define("tinymce/Editor", [
|
|
27806
27791
|
var self = this, elm;
|
27807
27792
|
|
27808
27793
|
if (!self.contentWindow) {
|
27809
|
-
elm =
|
27794
|
+
elm = self.iframeElement;
|
27810
27795
|
|
27811
27796
|
if (elm) {
|
27812
27797
|
self.contentWindow = elm.contentWindow;
|
@@ -27904,12 +27889,10 @@ define("tinymce/Editor", [
|
|
27904
27889
|
cls = settings.visual_table_class || 'mce-item-table';
|
27905
27890
|
value = dom.getAttrib(elm, 'border');
|
27906
27891
|
|
27907
|
-
if (!value || value == '0') {
|
27908
|
-
|
27909
|
-
|
27910
|
-
|
27911
|
-
dom.removeClass(elm, cls);
|
27912
|
-
}
|
27892
|
+
if ((!value || value == '0') && self.hasVisual) {
|
27893
|
+
dom.addClass(elm, cls);
|
27894
|
+
} else {
|
27895
|
+
dom.removeClass(elm, cls);
|
27913
27896
|
}
|
27914
27897
|
|
27915
27898
|
return;
|
@@ -27919,12 +27902,10 @@ define("tinymce/Editor", [
|
|
27919
27902
|
value = dom.getAttrib(elm, 'name') || elm.id;
|
27920
27903
|
cls = settings.visual_anchor_class || 'mce-item-anchor';
|
27921
27904
|
|
27922
|
-
if (value) {
|
27923
|
-
|
27924
|
-
|
27925
|
-
|
27926
|
-
dom.removeClass(elm, cls);
|
27927
|
-
}
|
27905
|
+
if (value && self.hasVisual) {
|
27906
|
+
dom.addClass(elm, cls);
|
27907
|
+
} else {
|
27908
|
+
dom.removeClass(elm, cls);
|
27928
27909
|
}
|
27929
27910
|
}
|
27930
27911
|
|
@@ -28035,7 +28016,8 @@ define("tinymce/Editor", [
|
|
28035
28016
|
}
|
28036
28017
|
|
28037
28018
|
self.contentAreaContainer = self.formElement = self.container = self.editorContainer = null;
|
28038
|
-
self.
|
28019
|
+
self.bodyElement = self.contentDocument = self.contentWindow = null;
|
28020
|
+
self.iframeElement = self.targetElm = null;
|
28039
28021
|
|
28040
28022
|
if (self.selection) {
|
28041
28023
|
self.selection = self.selection.win = self.selection.dom = self.selection.dom.doc = null;
|
@@ -28250,19 +28232,35 @@ define("tinymce/FocusManager", [
|
|
28250
28232
|
editor.on('init', function() {
|
28251
28233
|
// Gecko/WebKit has ghost selections in iframes and IE only has one selection per browser tab
|
28252
28234
|
if (editor.inline || Env.ie) {
|
28253
|
-
//
|
28254
|
-
|
28255
|
-
|
28235
|
+
// Use the onbeforedeactivate event when available since it works better see #7023
|
28236
|
+
if ("onbeforedeactivate" in document && Env.ie < 9) {
|
28237
|
+
editor.dom.bind(editor.getBody(), 'beforedeactivate', function() {
|
28238
|
+
try {
|
28239
|
+
editor.lastRng = editor.selection.getRng();
|
28240
|
+
} catch (ex) {
|
28241
|
+
// IE throws "Unexcpected call to method or property access" some times so lets ignore it
|
28242
|
+
}
|
28243
|
+
});
|
28244
|
+
} else {
|
28245
|
+
// On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
|
28246
|
+
editor.on('nodechange mouseup keyup', function(e) {
|
28247
|
+
var node = getActiveElement();
|
28256
28248
|
|
28257
|
-
|
28258
|
-
|
28259
|
-
|
28260
|
-
|
28249
|
+
// Only act on manual nodechanges
|
28250
|
+
if (e.type == 'nodechange' && e.selectionChange) {
|
28251
|
+
return;
|
28252
|
+
}
|
28261
28253
|
|
28262
|
-
|
28263
|
-
|
28264
|
-
|
28265
|
-
|
28254
|
+
// IE 11 reports active element as iframe not body of iframe
|
28255
|
+
if (node && node.id == editor.id + '_ifr') {
|
28256
|
+
node = editor.getBody();
|
28257
|
+
}
|
28258
|
+
|
28259
|
+
if (editor.dom.isChildOf(node, editor.getBody())) {
|
28260
|
+
editor.lastRng = editor.selection.getRng();
|
28261
|
+
}
|
28262
|
+
});
|
28263
|
+
}
|
28266
28264
|
|
28267
28265
|
// Handles the issue with WebKit not retaining selection within inline document
|
28268
28266
|
// If the user releases the mouse out side the body since a mouse up event wont occur on the body
|
@@ -28340,8 +28338,9 @@ define("tinymce/FocusManager", [
|
|
28340
28338
|
var activeEditor = editorManager.activeEditor;
|
28341
28339
|
|
28342
28340
|
if (activeEditor && e.target.ownerDocument == document) {
|
28343
|
-
// Check to make sure we have a valid selection
|
28344
|
-
|
28341
|
+
// Check to make sure we have a valid selection don't update the bookmark if it's
|
28342
|
+
// a focusin to the body of the editor see #7025
|
28343
|
+
if (activeEditor.selection && e.target != activeEditor.getBody()) {
|
28345
28344
|
activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.dom, activeEditor.lastRng);
|
28346
28345
|
}
|
28347
28346
|
|
@@ -28505,7 +28504,7 @@ define("tinymce/EditorManager", [
|
|
28505
28504
|
* @property minorVersion
|
28506
28505
|
* @type String
|
28507
28506
|
*/
|
28508
|
-
minorVersion: '1.
|
28507
|
+
minorVersion: '1.2',
|
28509
28508
|
|
28510
28509
|
/**
|
28511
28510
|
* Release date of TinyMCE build.
|
@@ -28513,7 +28512,7 @@ define("tinymce/EditorManager", [
|
|
28513
28512
|
* @property releaseDate
|
28514
28513
|
* @type String
|
28515
28514
|
*/
|
28516
|
-
releaseDate: '2014-
|
28515
|
+
releaseDate: '2014-07-15',
|
28517
28516
|
|
28518
28517
|
/**
|
28519
28518
|
* Collection of editor instances.
|
@@ -28673,26 +28672,27 @@ define("tinymce/EditorManager", [
|
|
28673
28672
|
return id;
|
28674
28673
|
}
|
28675
28674
|
|
28676
|
-
function createEditor(id, settings) {
|
28675
|
+
function createEditor(id, settings, targetElm) {
|
28677
28676
|
if (!purgeDestroyedEditor(self.get(id))) {
|
28678
28677
|
var editor = new Editor(id, settings, self);
|
28678
|
+
editor.targetElm = editor.targetElm || targetElm;
|
28679
28679
|
editors.push(editor);
|
28680
28680
|
editor.render();
|
28681
28681
|
}
|
28682
28682
|
}
|
28683
28683
|
|
28684
|
-
function execCallback(
|
28685
|
-
var
|
28684
|
+
function execCallback(name) {
|
28685
|
+
var callback = settings[name];
|
28686
28686
|
|
28687
|
-
if (!
|
28687
|
+
if (!callback) {
|
28688
28688
|
return;
|
28689
28689
|
}
|
28690
28690
|
|
28691
|
-
return
|
28691
|
+
return callback.apply(self, Array.prototype.slice.call(arguments, 2));
|
28692
28692
|
}
|
28693
28693
|
|
28694
|
-
function hasClass(
|
28695
|
-
return
|
28694
|
+
function hasClass(elm, className) {
|
28695
|
+
return className.constructor === RegExp ? className.test(elm.className) : DOM.hasClass(elm, className);
|
28696
28696
|
}
|
28697
28697
|
|
28698
28698
|
function readyHandler() {
|
@@ -28700,13 +28700,13 @@ define("tinymce/EditorManager", [
|
|
28700
28700
|
|
28701
28701
|
DOM.unbind(window, 'ready', readyHandler);
|
28702
28702
|
|
28703
|
-
execCallback(
|
28703
|
+
execCallback('onpageload');
|
28704
28704
|
|
28705
28705
|
if (settings.types) {
|
28706
28706
|
// Process type specific selector
|
28707
28707
|
each(settings.types, function(type) {
|
28708
28708
|
each(DOM.select(type.selector), function(elm) {
|
28709
|
-
createEditor(createId(elm), extend({}, settings, type));
|
28709
|
+
createEditor(createId(elm), extend({}, settings, type), elm);
|
28710
28710
|
});
|
28711
28711
|
});
|
28712
28712
|
|
@@ -28714,10 +28714,12 @@ define("tinymce/EditorManager", [
|
|
28714
28714
|
} else if (settings.selector) {
|
28715
28715
|
// Process global selector
|
28716
28716
|
each(DOM.select(settings.selector), function(elm) {
|
28717
|
-
createEditor(createId(elm), settings);
|
28717
|
+
createEditor(createId(elm), settings, elm);
|
28718
28718
|
});
|
28719
28719
|
|
28720
28720
|
return;
|
28721
|
+
} else if (settings.target) {
|
28722
|
+
createEditor(createId(settings.target), settings);
|
28721
28723
|
}
|
28722
28724
|
|
28723
28725
|
// Fallback to old setting
|
@@ -28737,7 +28739,7 @@ define("tinymce/EditorManager", [
|
|
28737
28739
|
if (e.name === v) {
|
28738
28740
|
v = 'mce_editor_' + instanceCounter++;
|
28739
28741
|
DOM.setAttrib(e, 'id', v);
|
28740
|
-
createEditor(v, settings);
|
28742
|
+
createEditor(v, settings, e);
|
28741
28743
|
}
|
28742
28744
|
});
|
28743
28745
|
});
|
@@ -28754,7 +28756,7 @@ define("tinymce/EditorManager", [
|
|
28754
28756
|
}
|
28755
28757
|
|
28756
28758
|
if (!settings.editor_selector || hasClass(elm, settings.editor_selector)) {
|
28757
|
-
createEditor(createId(elm), settings);
|
28759
|
+
createEditor(createId(elm), settings, elm);
|
28758
28760
|
}
|
28759
28761
|
});
|
28760
28762
|
break;
|
@@ -28774,7 +28776,7 @@ define("tinymce/EditorManager", [
|
|
28774
28776
|
|
28775
28777
|
// All done
|
28776
28778
|
if (l == co) {
|
28777
|
-
execCallback(
|
28779
|
+
execCallback('oninit');
|
28778
28780
|
}
|
28779
28781
|
});
|
28780
28782
|
} else {
|
@@ -28783,7 +28785,7 @@ define("tinymce/EditorManager", [
|
|
28783
28785
|
|
28784
28786
|
// All done
|
28785
28787
|
if (l == co) {
|
28786
|
-
execCallback(
|
28788
|
+
execCallback('oninit');
|
28787
28789
|
}
|
28788
28790
|
});
|
28789
28791
|
}
|
@@ -28903,7 +28905,11 @@ define("tinymce/EditorManager", [
|
|
28903
28905
|
selector = selector.selector || selector;
|
28904
28906
|
|
28905
28907
|
each(DOM.select(selector), function(elm) {
|
28906
|
-
|
28908
|
+
editor = editors[elm.id];
|
28909
|
+
|
28910
|
+
if (editor) {
|
28911
|
+
self.remove(editor);
|
28912
|
+
}
|
28907
28913
|
});
|
28908
28914
|
|
28909
28915
|
return;
|
@@ -31814,38 +31820,32 @@ define("tinymce/ui/ElementPath", [
|
|
31814
31820
|
}
|
31815
31821
|
|
31816
31822
|
self.on('select', function(e) {
|
31817
|
-
var parents = [], node, body = editor.getBody();
|
31818
|
-
|
31819
31823
|
editor.focus();
|
31820
|
-
|
31821
|
-
node = editor.selection.getStart();
|
31822
|
-
while (node && node != body) {
|
31823
|
-
if (!isHidden(node)) {
|
31824
|
-
parents.push(node);
|
31825
|
-
}
|
31826
|
-
|
31827
|
-
node = node.parentNode;
|
31828
|
-
}
|
31829
|
-
|
31830
|
-
editor.selection.select(parents[parents.length - 1 - e.index]);
|
31824
|
+
editor.selection.select(this.data()[e.index].element);
|
31831
31825
|
editor.nodeChanged();
|
31832
31826
|
});
|
31833
31827
|
|
31834
31828
|
editor.on('nodeChange', function(e) {
|
31835
|
-
var
|
31829
|
+
var outParents = [], parents = e.parents, i = parents.length;
|
31836
31830
|
|
31837
31831
|
while (i--) {
|
31838
|
-
if (
|
31832
|
+
if (parents[i].nodeType == 1 && !isHidden(parents[i])) {
|
31839
31833
|
var args = editor.fire('ResolveName', {
|
31840
|
-
name:
|
31841
|
-
target:
|
31834
|
+
name: parents[i].nodeName.toLowerCase(),
|
31835
|
+
target: parents[i]
|
31842
31836
|
});
|
31843
31837
|
|
31844
|
-
|
31838
|
+
if (!args.isDefaultPrevented()) {
|
31839
|
+
outParents.push({name: args.name, element: parents[i]});
|
31840
|
+
}
|
31841
|
+
|
31842
|
+
if (args.isPropagationStopped()) {
|
31843
|
+
break;
|
31844
|
+
}
|
31845
31845
|
}
|
31846
31846
|
}
|
31847
31847
|
|
31848
|
-
self.data(
|
31848
|
+
self.data(outParents);
|
31849
31849
|
});
|
31850
31850
|
|
31851
31851
|
return self._super();
|