tinymce-rails 4.0.28 → 4.0.28.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|