tinymce-rails 4.0.28 → 4.0.28.1
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/LICENSE +1 -1
- data/app/assets/source/tinymce/tinymce.jquery.js +388 -388
- data/app/assets/source/tinymce/tinymce.js +388 -388
- data/lib/tinymce/rails/engine.rb +19 -5
- data/lib/tinymce/rails/version.rb +1 -1
- metadata +4 -3
@@ -13363,394 +13363,394 @@ define("tinymce/dom/RangeUtils", [
|
|
13363
13363
|
|
13364
13364
|
// Included from: js/tinymce/classes/dom/BookmarkManager.js
|
13365
13365
|
|
13366
|
-
/**
|
13367
|
-
* BookmarkManager.js
|
13368
|
-
*
|
13369
|
-
* Copyright, Moxiecode Systems AB
|
13370
|
-
* Released under LGPL License.
|
13371
|
-
*
|
13372
|
-
* License: http://www.tinymce.com/license
|
13373
|
-
* Contributing: http://www.tinymce.com/contributing
|
13374
|
-
*/
|
13375
|
-
|
13376
|
-
/**
|
13377
|
-
* This class handles selection bookmarks.
|
13378
|
-
*
|
13379
|
-
* @class tinymce.dom.BookmarkManager
|
13380
|
-
*/
|
13381
|
-
define("tinymce/dom/BookmarkManager", [
|
13382
|
-
"tinymce/Env",
|
13383
|
-
"tinymce/util/Tools"
|
13384
|
-
], function(Env, Tools) {
|
13385
|
-
/**
|
13386
|
-
* Constructs a new BookmarkManager instance for a specific selection instance.
|
13387
|
-
*
|
13388
|
-
* @constructor
|
13389
|
-
* @method BookmarkManager
|
13390
|
-
* @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
|
13391
|
-
*/
|
13392
|
-
function BookmarkManager(selection) {
|
13393
|
-
var dom = selection.dom;
|
13394
|
-
|
13395
|
-
/**
|
13396
|
-
* Returns a bookmark location for the current selection. This bookmark object
|
13397
|
-
* can then be used to restore the selection after some content modification to the document.
|
13398
|
-
*
|
13399
|
-
* @method getBookmark
|
13400
|
-
* @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
|
13401
|
-
* @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
|
13402
|
-
* @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
|
13403
|
-
* @example
|
13404
|
-
* // Stores a bookmark of the current selection
|
13405
|
-
* var bm = tinymce.activeEditor.selection.getBookmark();
|
13406
|
-
*
|
13407
|
-
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
13408
|
-
*
|
13409
|
-
* // Restore the selection bookmark
|
13410
|
-
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
13411
|
-
*/
|
13412
|
-
this.getBookmark = function(type, normalized) {
|
13413
|
-
var rng, rng2, id, collapsed, name, element, chr = '', styles;
|
13414
|
-
|
13415
|
-
function findIndex(name, element) {
|
13416
|
-
var index = 0;
|
13417
|
-
|
13418
|
-
Tools.each(dom.select(name), function(node, i) {
|
13419
|
-
if (node == element) {
|
13420
|
-
index = i;
|
13421
|
-
}
|
13422
|
-
});
|
13423
|
-
|
13424
|
-
return index;
|
13425
|
-
}
|
13426
|
-
|
13427
|
-
function normalizeTableCellSelection(rng) {
|
13428
|
-
function moveEndPoint(start) {
|
13429
|
-
var container, offset, childNodes, prefix = start ? 'start' : 'end';
|
13430
|
-
|
13431
|
-
container = rng[prefix + 'Container'];
|
13432
|
-
offset = rng[prefix + 'Offset'];
|
13433
|
-
|
13434
|
-
if (container.nodeType == 1 && container.nodeName == "TR") {
|
13435
|
-
childNodes = container.childNodes;
|
13436
|
-
container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
|
13437
|
-
if (container) {
|
13438
|
-
offset = start ? 0 : container.childNodes.length;
|
13439
|
-
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
13440
|
-
}
|
13441
|
-
}
|
13442
|
-
}
|
13443
|
-
|
13444
|
-
moveEndPoint(true);
|
13445
|
-
moveEndPoint();
|
13446
|
-
|
13447
|
-
return rng;
|
13448
|
-
}
|
13449
|
-
|
13450
|
-
function getLocation() {
|
13451
|
-
var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
|
13452
|
-
|
13453
|
-
function getPoint(rng, start) {
|
13454
|
-
var container = rng[start ? 'startContainer' : 'endContainer'],
|
13455
|
-
offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
|
13456
|
-
|
13457
|
-
if (container.nodeType == 3) {
|
13458
|
-
if (normalized) {
|
13459
|
-
for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
|
13460
|
-
offset += node.nodeValue.length;
|
13461
|
-
}
|
13462
|
-
}
|
13463
|
-
|
13464
|
-
point.push(offset);
|
13465
|
-
} else {
|
13466
|
-
childNodes = container.childNodes;
|
13467
|
-
|
13468
|
-
if (offset >= childNodes.length && childNodes.length) {
|
13469
|
-
after = 1;
|
13470
|
-
offset = Math.max(0, childNodes.length - 1);
|
13471
|
-
}
|
13472
|
-
|
13473
|
-
point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
|
13474
|
-
}
|
13475
|
-
|
13476
|
-
for (; container && container != root; container = container.parentNode) {
|
13477
|
-
point.push(dom.nodeIndex(container, normalized));
|
13478
|
-
}
|
13479
|
-
|
13480
|
-
return point;
|
13481
|
-
}
|
13482
|
-
|
13483
|
-
bookmark.start = getPoint(rng, true);
|
13484
|
-
|
13485
|
-
if (!selection.isCollapsed()) {
|
13486
|
-
bookmark.end = getPoint(rng);
|
13487
|
-
}
|
13488
|
-
|
13489
|
-
return bookmark;
|
13490
|
-
}
|
13491
|
-
|
13492
|
-
if (type == 2) {
|
13493
|
-
element = selection.getNode();
|
13494
|
-
name = element ? element.nodeName : null;
|
13495
|
-
|
13496
|
-
if (name == 'IMG') {
|
13497
|
-
return {name: name, index: findIndex(name, element)};
|
13498
|
-
}
|
13499
|
-
|
13500
|
-
if (selection.tridentSel) {
|
13501
|
-
return selection.tridentSel.getBookmark(type);
|
13502
|
-
}
|
13503
|
-
|
13504
|
-
return getLocation();
|
13505
|
-
}
|
13506
|
-
|
13507
|
-
// Handle simple range
|
13508
|
-
if (type) {
|
13509
|
-
return {rng: selection.getRng()};
|
13510
|
-
}
|
13511
|
-
|
13512
|
-
rng = selection.getRng();
|
13513
|
-
id = dom.uniqueId();
|
13514
|
-
collapsed = selection.isCollapsed();
|
13515
|
-
styles = 'overflow:hidden;line-height:0px';
|
13516
|
-
|
13517
|
-
// Explorer method
|
13518
|
-
if (rng.duplicate || rng.item) {
|
13519
|
-
// Text selection
|
13520
|
-
if (!rng.item) {
|
13521
|
-
rng2 = rng.duplicate();
|
13522
|
-
|
13523
|
-
try {
|
13524
|
-
// Insert start marker
|
13525
|
-
rng.collapse();
|
13526
|
-
rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
|
13527
|
-
|
13528
|
-
// Insert end marker
|
13529
|
-
if (!collapsed) {
|
13530
|
-
rng2.collapse(false);
|
13531
|
-
|
13532
|
-
// Detect the empty space after block elements in IE and move the
|
13533
|
-
// end back one character <p></p>] becomes <p>]</p>
|
13534
|
-
rng.moveToElementText(rng2.parentElement());
|
13535
|
-
if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
|
13536
|
-
rng2.move('character', -1);
|
13537
|
-
}
|
13538
|
-
|
13539
|
-
rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
|
13540
|
-
}
|
13541
|
-
} catch (ex) {
|
13542
|
-
// IE might throw unspecified error so lets ignore it
|
13543
|
-
return null;
|
13544
|
-
}
|
13545
|
-
} else {
|
13546
|
-
// Control selection
|
13547
|
-
element = rng.item(0);
|
13548
|
-
name = element.nodeName;
|
13549
|
-
|
13550
|
-
return {name: name, index: findIndex(name, element)};
|
13551
|
-
}
|
13552
|
-
} else {
|
13553
|
-
element = selection.getNode();
|
13554
|
-
name = element.nodeName;
|
13555
|
-
if (name == 'IMG') {
|
13556
|
-
return {name: name, index: findIndex(name, element)};
|
13557
|
-
}
|
13558
|
-
|
13559
|
-
// W3C method
|
13560
|
-
rng2 = normalizeTableCellSelection(rng.cloneRange());
|
13561
|
-
|
13562
|
-
// Insert end marker
|
13563
|
-
if (!collapsed) {
|
13564
|
-
rng2.collapse(false);
|
13565
|
-
rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
|
13566
|
-
}
|
13567
|
-
|
13568
|
-
rng = normalizeTableCellSelection(rng);
|
13569
|
-
rng.collapse(true);
|
13570
|
-
rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
|
13571
|
-
}
|
13572
|
-
|
13573
|
-
selection.moveToBookmark({id: id, keep: 1});
|
13574
|
-
|
13575
|
-
return {id: id};
|
13576
|
-
};
|
13577
|
-
|
13578
|
-
/**
|
13579
|
-
* Restores the selection to the specified bookmark.
|
13580
|
-
*
|
13581
|
-
* @method moveToBookmark
|
13582
|
-
* @param {Object} bookmark Bookmark to restore selection from.
|
13583
|
-
* @return {Boolean} true/false if it was successful or not.
|
13584
|
-
* @example
|
13585
|
-
* // Stores a bookmark of the current selection
|
13586
|
-
* var bm = tinymce.activeEditor.selection.getBookmark();
|
13587
|
-
*
|
13588
|
-
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
13589
|
-
*
|
13590
|
-
* // Restore the selection bookmark
|
13591
|
-
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
13592
|
-
*/
|
13593
|
-
this.moveToBookmark = function(bookmark) {
|
13594
|
-
var rng, root, startContainer, endContainer, startOffset, endOffset;
|
13595
|
-
|
13596
|
-
function setEndPoint(start) {
|
13597
|
-
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
|
13598
|
-
|
13599
|
-
if (point) {
|
13600
|
-
offset = point[0];
|
13601
|
-
|
13602
|
-
// Find container node
|
13603
|
-
for (node = root, i = point.length - 1; i >= 1; i--) {
|
13604
|
-
children = node.childNodes;
|
13605
|
-
|
13606
|
-
if (point[i] > children.length - 1) {
|
13607
|
-
return;
|
13608
|
-
}
|
13609
|
-
|
13610
|
-
node = children[point[i]];
|
13611
|
-
}
|
13612
|
-
|
13613
|
-
// Move text offset to best suitable location
|
13614
|
-
if (node.nodeType === 3) {
|
13615
|
-
offset = Math.min(point[0], node.nodeValue.length);
|
13616
|
-
}
|
13617
|
-
|
13618
|
-
// Move element offset to best suitable location
|
13619
|
-
if (node.nodeType === 1) {
|
13620
|
-
offset = Math.min(point[0], node.childNodes.length);
|
13621
|
-
}
|
13622
|
-
|
13623
|
-
// Set offset within container node
|
13624
|
-
if (start) {
|
13625
|
-
rng.setStart(node, offset);
|
13626
|
-
} else {
|
13627
|
-
rng.setEnd(node, offset);
|
13628
|
-
}
|
13629
|
-
}
|
13630
|
-
|
13631
|
-
return true;
|
13632
|
-
}
|
13633
|
-
|
13634
|
-
function restoreEndPoint(suffix) {
|
13635
|
-
var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
|
13636
|
-
|
13637
|
-
if (marker) {
|
13638
|
-
node = marker.parentNode;
|
13639
|
-
|
13640
|
-
if (suffix == 'start') {
|
13641
|
-
if (!keep) {
|
13642
|
-
idx = dom.nodeIndex(marker);
|
13643
|
-
} else {
|
13644
|
-
node = marker.firstChild;
|
13645
|
-
idx = 1;
|
13646
|
-
}
|
13647
|
-
|
13648
|
-
startContainer = endContainer = node;
|
13649
|
-
startOffset = endOffset = idx;
|
13650
|
-
} else {
|
13651
|
-
if (!keep) {
|
13652
|
-
idx = dom.nodeIndex(marker);
|
13653
|
-
} else {
|
13654
|
-
node = marker.firstChild;
|
13655
|
-
idx = 1;
|
13656
|
-
}
|
13657
|
-
|
13658
|
-
endContainer = node;
|
13659
|
-
endOffset = idx;
|
13660
|
-
}
|
13661
|
-
|
13662
|
-
if (!keep) {
|
13663
|
-
prev = marker.previousSibling;
|
13664
|
-
next = marker.nextSibling;
|
13665
|
-
|
13666
|
-
// Remove all marker text nodes
|
13667
|
-
Tools.each(Tools.grep(marker.childNodes), function(node) {
|
13668
|
-
if (node.nodeType == 3) {
|
13669
|
-
node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
|
13670
|
-
}
|
13671
|
-
});
|
13672
|
-
|
13673
|
-
// Remove marker but keep children if for example contents where inserted into the marker
|
13674
|
-
// Also remove duplicated instances of the marker for example by a
|
13675
|
-
// split operation or by WebKit auto split on paste feature
|
13676
|
-
while ((marker = dom.get(bookmark.id + '_' + suffix))) {
|
13677
|
-
dom.remove(marker, 1);
|
13678
|
-
}
|
13679
|
-
|
13680
|
-
// If siblings are text nodes then merge them unless it's Opera since it some how removes the node
|
13681
|
-
// and we are sniffing since adding a lot of detection code for a browser with 3% of the market
|
13682
|
-
// isn't worth the effort. Sorry, Opera but it's just a fact
|
13683
|
-
if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
|
13684
|
-
idx = prev.nodeValue.length;
|
13685
|
-
prev.appendData(next.nodeValue);
|
13686
|
-
dom.remove(next);
|
13687
|
-
|
13688
|
-
if (suffix == 'start') {
|
13689
|
-
startContainer = endContainer = prev;
|
13690
|
-
startOffset = endOffset = idx;
|
13691
|
-
} else {
|
13692
|
-
endContainer = prev;
|
13693
|
-
endOffset = idx;
|
13694
|
-
}
|
13695
|
-
}
|
13696
|
-
}
|
13697
|
-
}
|
13698
|
-
}
|
13699
|
-
|
13700
|
-
function addBogus(node) {
|
13701
|
-
// Adds a bogus BR element for empty block elements
|
13702
|
-
if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
|
13703
|
-
node.innerHTML = '<br data-mce-bogus="1" />';
|
13704
|
-
}
|
13705
|
-
|
13706
|
-
return node;
|
13707
|
-
}
|
13708
|
-
|
13709
|
-
if (bookmark) {
|
13710
|
-
if (bookmark.start) {
|
13711
|
-
rng = dom.createRng();
|
13712
|
-
root = dom.getRoot();
|
13713
|
-
|
13714
|
-
if (selection.tridentSel) {
|
13715
|
-
return selection.tridentSel.moveToBookmark(bookmark);
|
13716
|
-
}
|
13717
|
-
|
13718
|
-
if (setEndPoint(true) && setEndPoint()) {
|
13719
|
-
selection.setRng(rng);
|
13720
|
-
}
|
13721
|
-
} else if (bookmark.id) {
|
13722
|
-
// Restore start/end points
|
13723
|
-
restoreEndPoint('start');
|
13724
|
-
restoreEndPoint('end');
|
13725
|
-
|
13726
|
-
if (startContainer) {
|
13727
|
-
rng = dom.createRng();
|
13728
|
-
rng.setStart(addBogus(startContainer), startOffset);
|
13729
|
-
rng.setEnd(addBogus(endContainer), endOffset);
|
13730
|
-
selection.setRng(rng);
|
13731
|
-
}
|
13732
|
-
} else if (bookmark.name) {
|
13733
|
-
selection.select(dom.select(bookmark.name)[bookmark.index]);
|
13734
|
-
} else if (bookmark.rng) {
|
13735
|
-
selection.setRng(bookmark.rng);
|
13736
|
-
}
|
13737
|
-
}
|
13738
|
-
};
|
13739
|
-
}
|
13740
|
-
|
13741
|
-
/**
|
13742
|
-
* Returns true/false if the specified node is a bookmark node or not.
|
13743
|
-
*
|
13744
|
-
* @static
|
13745
|
-
* @method isBookmarkNode
|
13746
|
-
* @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
|
13747
|
-
* @return {Boolean} true/false if the node is a bookmark node or not.
|
13748
|
-
*/
|
13749
|
-
BookmarkManager.isBookmarkNode = function(node) {
|
13750
|
-
return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
|
13751
|
-
};
|
13752
|
-
|
13753
|
-
return BookmarkManager;
|
13366
|
+
/**
|
13367
|
+
* BookmarkManager.js
|
13368
|
+
*
|
13369
|
+
* Copyright, Moxiecode Systems AB
|
13370
|
+
* Released under LGPL License.
|
13371
|
+
*
|
13372
|
+
* License: http://www.tinymce.com/license
|
13373
|
+
* Contributing: http://www.tinymce.com/contributing
|
13374
|
+
*/
|
13375
|
+
|
13376
|
+
/**
|
13377
|
+
* This class handles selection bookmarks.
|
13378
|
+
*
|
13379
|
+
* @class tinymce.dom.BookmarkManager
|
13380
|
+
*/
|
13381
|
+
define("tinymce/dom/BookmarkManager", [
|
13382
|
+
"tinymce/Env",
|
13383
|
+
"tinymce/util/Tools"
|
13384
|
+
], function(Env, Tools) {
|
13385
|
+
/**
|
13386
|
+
* Constructs a new BookmarkManager instance for a specific selection instance.
|
13387
|
+
*
|
13388
|
+
* @constructor
|
13389
|
+
* @method BookmarkManager
|
13390
|
+
* @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
|
13391
|
+
*/
|
13392
|
+
function BookmarkManager(selection) {
|
13393
|
+
var dom = selection.dom;
|
13394
|
+
|
13395
|
+
/**
|
13396
|
+
* Returns a bookmark location for the current selection. This bookmark object
|
13397
|
+
* can then be used to restore the selection after some content modification to the document.
|
13398
|
+
*
|
13399
|
+
* @method getBookmark
|
13400
|
+
* @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
|
13401
|
+
* @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
|
13402
|
+
* @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
|
13403
|
+
* @example
|
13404
|
+
* // Stores a bookmark of the current selection
|
13405
|
+
* var bm = tinymce.activeEditor.selection.getBookmark();
|
13406
|
+
*
|
13407
|
+
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
13408
|
+
*
|
13409
|
+
* // Restore the selection bookmark
|
13410
|
+
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
13411
|
+
*/
|
13412
|
+
this.getBookmark = function(type, normalized) {
|
13413
|
+
var rng, rng2, id, collapsed, name, element, chr = '', styles;
|
13414
|
+
|
13415
|
+
function findIndex(name, element) {
|
13416
|
+
var index = 0;
|
13417
|
+
|
13418
|
+
Tools.each(dom.select(name), function(node, i) {
|
13419
|
+
if (node == element) {
|
13420
|
+
index = i;
|
13421
|
+
}
|
13422
|
+
});
|
13423
|
+
|
13424
|
+
return index;
|
13425
|
+
}
|
13426
|
+
|
13427
|
+
function normalizeTableCellSelection(rng) {
|
13428
|
+
function moveEndPoint(start) {
|
13429
|
+
var container, offset, childNodes, prefix = start ? 'start' : 'end';
|
13430
|
+
|
13431
|
+
container = rng[prefix + 'Container'];
|
13432
|
+
offset = rng[prefix + 'Offset'];
|
13433
|
+
|
13434
|
+
if (container.nodeType == 1 && container.nodeName == "TR") {
|
13435
|
+
childNodes = container.childNodes;
|
13436
|
+
container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
|
13437
|
+
if (container) {
|
13438
|
+
offset = start ? 0 : container.childNodes.length;
|
13439
|
+
rng['set' + (start ? 'Start' : 'End')](container, offset);
|
13440
|
+
}
|
13441
|
+
}
|
13442
|
+
}
|
13443
|
+
|
13444
|
+
moveEndPoint(true);
|
13445
|
+
moveEndPoint();
|
13446
|
+
|
13447
|
+
return rng;
|
13448
|
+
}
|
13449
|
+
|
13450
|
+
function getLocation() {
|
13451
|
+
var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
|
13452
|
+
|
13453
|
+
function getPoint(rng, start) {
|
13454
|
+
var container = rng[start ? 'startContainer' : 'endContainer'],
|
13455
|
+
offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
|
13456
|
+
|
13457
|
+
if (container.nodeType == 3) {
|
13458
|
+
if (normalized) {
|
13459
|
+
for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
|
13460
|
+
offset += node.nodeValue.length;
|
13461
|
+
}
|
13462
|
+
}
|
13463
|
+
|
13464
|
+
point.push(offset);
|
13465
|
+
} else {
|
13466
|
+
childNodes = container.childNodes;
|
13467
|
+
|
13468
|
+
if (offset >= childNodes.length && childNodes.length) {
|
13469
|
+
after = 1;
|
13470
|
+
offset = Math.max(0, childNodes.length - 1);
|
13471
|
+
}
|
13472
|
+
|
13473
|
+
point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
|
13474
|
+
}
|
13475
|
+
|
13476
|
+
for (; container && container != root; container = container.parentNode) {
|
13477
|
+
point.push(dom.nodeIndex(container, normalized));
|
13478
|
+
}
|
13479
|
+
|
13480
|
+
return point;
|
13481
|
+
}
|
13482
|
+
|
13483
|
+
bookmark.start = getPoint(rng, true);
|
13484
|
+
|
13485
|
+
if (!selection.isCollapsed()) {
|
13486
|
+
bookmark.end = getPoint(rng);
|
13487
|
+
}
|
13488
|
+
|
13489
|
+
return bookmark;
|
13490
|
+
}
|
13491
|
+
|
13492
|
+
if (type == 2) {
|
13493
|
+
element = selection.getNode();
|
13494
|
+
name = element ? element.nodeName : null;
|
13495
|
+
|
13496
|
+
if (name == 'IMG') {
|
13497
|
+
return {name: name, index: findIndex(name, element)};
|
13498
|
+
}
|
13499
|
+
|
13500
|
+
if (selection.tridentSel) {
|
13501
|
+
return selection.tridentSel.getBookmark(type);
|
13502
|
+
}
|
13503
|
+
|
13504
|
+
return getLocation();
|
13505
|
+
}
|
13506
|
+
|
13507
|
+
// Handle simple range
|
13508
|
+
if (type) {
|
13509
|
+
return {rng: selection.getRng()};
|
13510
|
+
}
|
13511
|
+
|
13512
|
+
rng = selection.getRng();
|
13513
|
+
id = dom.uniqueId();
|
13514
|
+
collapsed = selection.isCollapsed();
|
13515
|
+
styles = 'overflow:hidden;line-height:0px';
|
13516
|
+
|
13517
|
+
// Explorer method
|
13518
|
+
if (rng.duplicate || rng.item) {
|
13519
|
+
// Text selection
|
13520
|
+
if (!rng.item) {
|
13521
|
+
rng2 = rng.duplicate();
|
13522
|
+
|
13523
|
+
try {
|
13524
|
+
// Insert start marker
|
13525
|
+
rng.collapse();
|
13526
|
+
rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
|
13527
|
+
|
13528
|
+
// Insert end marker
|
13529
|
+
if (!collapsed) {
|
13530
|
+
rng2.collapse(false);
|
13531
|
+
|
13532
|
+
// Detect the empty space after block elements in IE and move the
|
13533
|
+
// end back one character <p></p>] becomes <p>]</p>
|
13534
|
+
rng.moveToElementText(rng2.parentElement());
|
13535
|
+
if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
|
13536
|
+
rng2.move('character', -1);
|
13537
|
+
}
|
13538
|
+
|
13539
|
+
rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
|
13540
|
+
}
|
13541
|
+
} catch (ex) {
|
13542
|
+
// IE might throw unspecified error so lets ignore it
|
13543
|
+
return null;
|
13544
|
+
}
|
13545
|
+
} else {
|
13546
|
+
// Control selection
|
13547
|
+
element = rng.item(0);
|
13548
|
+
name = element.nodeName;
|
13549
|
+
|
13550
|
+
return {name: name, index: findIndex(name, element)};
|
13551
|
+
}
|
13552
|
+
} else {
|
13553
|
+
element = selection.getNode();
|
13554
|
+
name = element.nodeName;
|
13555
|
+
if (name == 'IMG') {
|
13556
|
+
return {name: name, index: findIndex(name, element)};
|
13557
|
+
}
|
13558
|
+
|
13559
|
+
// W3C method
|
13560
|
+
rng2 = normalizeTableCellSelection(rng.cloneRange());
|
13561
|
+
|
13562
|
+
// Insert end marker
|
13563
|
+
if (!collapsed) {
|
13564
|
+
rng2.collapse(false);
|
13565
|
+
rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
|
13566
|
+
}
|
13567
|
+
|
13568
|
+
rng = normalizeTableCellSelection(rng);
|
13569
|
+
rng.collapse(true);
|
13570
|
+
rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
|
13571
|
+
}
|
13572
|
+
|
13573
|
+
selection.moveToBookmark({id: id, keep: 1});
|
13574
|
+
|
13575
|
+
return {id: id};
|
13576
|
+
};
|
13577
|
+
|
13578
|
+
/**
|
13579
|
+
* Restores the selection to the specified bookmark.
|
13580
|
+
*
|
13581
|
+
* @method moveToBookmark
|
13582
|
+
* @param {Object} bookmark Bookmark to restore selection from.
|
13583
|
+
* @return {Boolean} true/false if it was successful or not.
|
13584
|
+
* @example
|
13585
|
+
* // Stores a bookmark of the current selection
|
13586
|
+
* var bm = tinymce.activeEditor.selection.getBookmark();
|
13587
|
+
*
|
13588
|
+
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
13589
|
+
*
|
13590
|
+
* // Restore the selection bookmark
|
13591
|
+
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
13592
|
+
*/
|
13593
|
+
this.moveToBookmark = function(bookmark) {
|
13594
|
+
var rng, root, startContainer, endContainer, startOffset, endOffset;
|
13595
|
+
|
13596
|
+
function setEndPoint(start) {
|
13597
|
+
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
|
13598
|
+
|
13599
|
+
if (point) {
|
13600
|
+
offset = point[0];
|
13601
|
+
|
13602
|
+
// Find container node
|
13603
|
+
for (node = root, i = point.length - 1; i >= 1; i--) {
|
13604
|
+
children = node.childNodes;
|
13605
|
+
|
13606
|
+
if (point[i] > children.length - 1) {
|
13607
|
+
return;
|
13608
|
+
}
|
13609
|
+
|
13610
|
+
node = children[point[i]];
|
13611
|
+
}
|
13612
|
+
|
13613
|
+
// Move text offset to best suitable location
|
13614
|
+
if (node.nodeType === 3) {
|
13615
|
+
offset = Math.min(point[0], node.nodeValue.length);
|
13616
|
+
}
|
13617
|
+
|
13618
|
+
// Move element offset to best suitable location
|
13619
|
+
if (node.nodeType === 1) {
|
13620
|
+
offset = Math.min(point[0], node.childNodes.length);
|
13621
|
+
}
|
13622
|
+
|
13623
|
+
// Set offset within container node
|
13624
|
+
if (start) {
|
13625
|
+
rng.setStart(node, offset);
|
13626
|
+
} else {
|
13627
|
+
rng.setEnd(node, offset);
|
13628
|
+
}
|
13629
|
+
}
|
13630
|
+
|
13631
|
+
return true;
|
13632
|
+
}
|
13633
|
+
|
13634
|
+
function restoreEndPoint(suffix) {
|
13635
|
+
var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
|
13636
|
+
|
13637
|
+
if (marker) {
|
13638
|
+
node = marker.parentNode;
|
13639
|
+
|
13640
|
+
if (suffix == 'start') {
|
13641
|
+
if (!keep) {
|
13642
|
+
idx = dom.nodeIndex(marker);
|
13643
|
+
} else {
|
13644
|
+
node = marker.firstChild;
|
13645
|
+
idx = 1;
|
13646
|
+
}
|
13647
|
+
|
13648
|
+
startContainer = endContainer = node;
|
13649
|
+
startOffset = endOffset = idx;
|
13650
|
+
} else {
|
13651
|
+
if (!keep) {
|
13652
|
+
idx = dom.nodeIndex(marker);
|
13653
|
+
} else {
|
13654
|
+
node = marker.firstChild;
|
13655
|
+
idx = 1;
|
13656
|
+
}
|
13657
|
+
|
13658
|
+
endContainer = node;
|
13659
|
+
endOffset = idx;
|
13660
|
+
}
|
13661
|
+
|
13662
|
+
if (!keep) {
|
13663
|
+
prev = marker.previousSibling;
|
13664
|
+
next = marker.nextSibling;
|
13665
|
+
|
13666
|
+
// Remove all marker text nodes
|
13667
|
+
Tools.each(Tools.grep(marker.childNodes), function(node) {
|
13668
|
+
if (node.nodeType == 3) {
|
13669
|
+
node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
|
13670
|
+
}
|
13671
|
+
});
|
13672
|
+
|
13673
|
+
// Remove marker but keep children if for example contents where inserted into the marker
|
13674
|
+
// Also remove duplicated instances of the marker for example by a
|
13675
|
+
// split operation or by WebKit auto split on paste feature
|
13676
|
+
while ((marker = dom.get(bookmark.id + '_' + suffix))) {
|
13677
|
+
dom.remove(marker, 1);
|
13678
|
+
}
|
13679
|
+
|
13680
|
+
// If siblings are text nodes then merge them unless it's Opera since it some how removes the node
|
13681
|
+
// and we are sniffing since adding a lot of detection code for a browser with 3% of the market
|
13682
|
+
// isn't worth the effort. Sorry, Opera but it's just a fact
|
13683
|
+
if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
|
13684
|
+
idx = prev.nodeValue.length;
|
13685
|
+
prev.appendData(next.nodeValue);
|
13686
|
+
dom.remove(next);
|
13687
|
+
|
13688
|
+
if (suffix == 'start') {
|
13689
|
+
startContainer = endContainer = prev;
|
13690
|
+
startOffset = endOffset = idx;
|
13691
|
+
} else {
|
13692
|
+
endContainer = prev;
|
13693
|
+
endOffset = idx;
|
13694
|
+
}
|
13695
|
+
}
|
13696
|
+
}
|
13697
|
+
}
|
13698
|
+
}
|
13699
|
+
|
13700
|
+
function addBogus(node) {
|
13701
|
+
// Adds a bogus BR element for empty block elements
|
13702
|
+
if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
|
13703
|
+
node.innerHTML = '<br data-mce-bogus="1" />';
|
13704
|
+
}
|
13705
|
+
|
13706
|
+
return node;
|
13707
|
+
}
|
13708
|
+
|
13709
|
+
if (bookmark) {
|
13710
|
+
if (bookmark.start) {
|
13711
|
+
rng = dom.createRng();
|
13712
|
+
root = dom.getRoot();
|
13713
|
+
|
13714
|
+
if (selection.tridentSel) {
|
13715
|
+
return selection.tridentSel.moveToBookmark(bookmark);
|
13716
|
+
}
|
13717
|
+
|
13718
|
+
if (setEndPoint(true) && setEndPoint()) {
|
13719
|
+
selection.setRng(rng);
|
13720
|
+
}
|
13721
|
+
} else if (bookmark.id) {
|
13722
|
+
// Restore start/end points
|
13723
|
+
restoreEndPoint('start');
|
13724
|
+
restoreEndPoint('end');
|
13725
|
+
|
13726
|
+
if (startContainer) {
|
13727
|
+
rng = dom.createRng();
|
13728
|
+
rng.setStart(addBogus(startContainer), startOffset);
|
13729
|
+
rng.setEnd(addBogus(endContainer), endOffset);
|
13730
|
+
selection.setRng(rng);
|
13731
|
+
}
|
13732
|
+
} else if (bookmark.name) {
|
13733
|
+
selection.select(dom.select(bookmark.name)[bookmark.index]);
|
13734
|
+
} else if (bookmark.rng) {
|
13735
|
+
selection.setRng(bookmark.rng);
|
13736
|
+
}
|
13737
|
+
}
|
13738
|
+
};
|
13739
|
+
}
|
13740
|
+
|
13741
|
+
/**
|
13742
|
+
* Returns true/false if the specified node is a bookmark node or not.
|
13743
|
+
*
|
13744
|
+
* @static
|
13745
|
+
* @method isBookmarkNode
|
13746
|
+
* @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
|
13747
|
+
* @return {Boolean} true/false if the node is a bookmark node or not.
|
13748
|
+
*/
|
13749
|
+
BookmarkManager.isBookmarkNode = function(node) {
|
13750
|
+
return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
|
13751
|
+
};
|
13752
|
+
|
13753
|
+
return BookmarkManager;
|
13754
13754
|
});
|
13755
13755
|
|
13756
13756
|
// Included from: js/tinymce/classes/dom/Selection.js
|