tinymce-rails 4.1.0 → 4.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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();
|