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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d61de30fa04cae313a1896b6cb9326acb089427
4
- data.tar.gz: c505df76105015340cc701707fda4801201756ee
3
+ metadata.gz: bbb5b0491068647580afdb55641b93c7e91934d3
4
+ data.tar.gz: 34adddab7097e20a69eafbb5a1d54c65cd66d8c0
5
5
  SHA512:
6
- metadata.gz: 43bd86134162aa09da12d021d390f0795a1eeaa064b4eaa7b9a3daa5ce07cca60a777ac350c9cde96d495acd094a4a116f7020067c1b71a4cf2aec8513659399
7
- data.tar.gz: cdf88d954d3b887f44a2a4f4e9834c5657a87659e9e9440a44d748dc52150957bc5d63dcb4a5cac3fe2d5543c4e930890d2870917e4e30435e46209d7c08ee0e
6
+ metadata.gz: 3ce49cdff4a6fc645ee7db3274bb96ff164def6a64b3cc1ba1543d17a364cb17bc49a2d39a762185af7b110076679be9153fa1fdac05647cb534a533555d73fb
7
+ data.tar.gz: 74ccf99309c13c99b3b25cbbb3edebfd20b0e0125383a93811a6739b1df8dbfee279dfce8c3fe7e4b9733e28946d37fa7b1b9267536c0c38c89f403de0e5ebc7
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2011-13 by Sam Pohlenz
1
+ Copyright (C) 2011-14 by Sam Pohlenz
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -10725,394 +10725,394 @@ define("tinymce/dom/RangeUtils", [
10725
10725
 
10726
10726
  // Included from: js/tinymce/classes/dom/BookmarkManager.js
10727
10727
 
10728
- /**
10729
- * BookmarkManager.js
10730
- *
10731
- * Copyright, Moxiecode Systems AB
10732
- * Released under LGPL License.
10733
- *
10734
- * License: http://www.tinymce.com/license
10735
- * Contributing: http://www.tinymce.com/contributing
10736
- */
10737
-
10738
- /**
10739
- * This class handles selection bookmarks.
10740
- *
10741
- * @class tinymce.dom.BookmarkManager
10742
- */
10743
- define("tinymce/dom/BookmarkManager", [
10744
- "tinymce/Env",
10745
- "tinymce/util/Tools"
10746
- ], function(Env, Tools) {
10747
- /**
10748
- * Constructs a new BookmarkManager instance for a specific selection instance.
10749
- *
10750
- * @constructor
10751
- * @method BookmarkManager
10752
- * @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
10753
- */
10754
- function BookmarkManager(selection) {
10755
- var dom = selection.dom;
10756
-
10757
- /**
10758
- * Returns a bookmark location for the current selection. This bookmark object
10759
- * can then be used to restore the selection after some content modification to the document.
10760
- *
10761
- * @method getBookmark
10762
- * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
10763
- * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
10764
- * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
10765
- * @example
10766
- * // Stores a bookmark of the current selection
10767
- * var bm = tinymce.activeEditor.selection.getBookmark();
10768
- *
10769
- * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
10770
- *
10771
- * // Restore the selection bookmark
10772
- * tinymce.activeEditor.selection.moveToBookmark(bm);
10773
- */
10774
- this.getBookmark = function(type, normalized) {
10775
- var rng, rng2, id, collapsed, name, element, chr = '', styles;
10776
-
10777
- function findIndex(name, element) {
10778
- var index = 0;
10779
-
10780
- Tools.each(dom.select(name), function(node, i) {
10781
- if (node == element) {
10782
- index = i;
10783
- }
10784
- });
10785
-
10786
- return index;
10787
- }
10788
-
10789
- function normalizeTableCellSelection(rng) {
10790
- function moveEndPoint(start) {
10791
- var container, offset, childNodes, prefix = start ? 'start' : 'end';
10792
-
10793
- container = rng[prefix + 'Container'];
10794
- offset = rng[prefix + 'Offset'];
10795
-
10796
- if (container.nodeType == 1 && container.nodeName == "TR") {
10797
- childNodes = container.childNodes;
10798
- container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
10799
- if (container) {
10800
- offset = start ? 0 : container.childNodes.length;
10801
- rng['set' + (start ? 'Start' : 'End')](container, offset);
10802
- }
10803
- }
10804
- }
10805
-
10806
- moveEndPoint(true);
10807
- moveEndPoint();
10808
-
10809
- return rng;
10810
- }
10811
-
10812
- function getLocation() {
10813
- var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
10814
-
10815
- function getPoint(rng, start) {
10816
- var container = rng[start ? 'startContainer' : 'endContainer'],
10817
- offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
10818
-
10819
- if (container.nodeType == 3) {
10820
- if (normalized) {
10821
- for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
10822
- offset += node.nodeValue.length;
10823
- }
10824
- }
10825
-
10826
- point.push(offset);
10827
- } else {
10828
- childNodes = container.childNodes;
10829
-
10830
- if (offset >= childNodes.length && childNodes.length) {
10831
- after = 1;
10832
- offset = Math.max(0, childNodes.length - 1);
10833
- }
10834
-
10835
- point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
10836
- }
10837
-
10838
- for (; container && container != root; container = container.parentNode) {
10839
- point.push(dom.nodeIndex(container, normalized));
10840
- }
10841
-
10842
- return point;
10843
- }
10844
-
10845
- bookmark.start = getPoint(rng, true);
10846
-
10847
- if (!selection.isCollapsed()) {
10848
- bookmark.end = getPoint(rng);
10849
- }
10850
-
10851
- return bookmark;
10852
- }
10853
-
10854
- if (type == 2) {
10855
- element = selection.getNode();
10856
- name = element ? element.nodeName : null;
10857
-
10858
- if (name == 'IMG') {
10859
- return {name: name, index: findIndex(name, element)};
10860
- }
10861
-
10862
- if (selection.tridentSel) {
10863
- return selection.tridentSel.getBookmark(type);
10864
- }
10865
-
10866
- return getLocation();
10867
- }
10868
-
10869
- // Handle simple range
10870
- if (type) {
10871
- return {rng: selection.getRng()};
10872
- }
10873
-
10874
- rng = selection.getRng();
10875
- id = dom.uniqueId();
10876
- collapsed = selection.isCollapsed();
10877
- styles = 'overflow:hidden;line-height:0px';
10878
-
10879
- // Explorer method
10880
- if (rng.duplicate || rng.item) {
10881
- // Text selection
10882
- if (!rng.item) {
10883
- rng2 = rng.duplicate();
10884
-
10885
- try {
10886
- // Insert start marker
10887
- rng.collapse();
10888
- rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
10889
-
10890
- // Insert end marker
10891
- if (!collapsed) {
10892
- rng2.collapse(false);
10893
-
10894
- // Detect the empty space after block elements in IE and move the
10895
- // end back one character <p></p>] becomes <p>]</p>
10896
- rng.moveToElementText(rng2.parentElement());
10897
- if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
10898
- rng2.move('character', -1);
10899
- }
10900
-
10901
- rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
10902
- }
10903
- } catch (ex) {
10904
- // IE might throw unspecified error so lets ignore it
10905
- return null;
10906
- }
10907
- } else {
10908
- // Control selection
10909
- element = rng.item(0);
10910
- name = element.nodeName;
10911
-
10912
- return {name: name, index: findIndex(name, element)};
10913
- }
10914
- } else {
10915
- element = selection.getNode();
10916
- name = element.nodeName;
10917
- if (name == 'IMG') {
10918
- return {name: name, index: findIndex(name, element)};
10919
- }
10920
-
10921
- // W3C method
10922
- rng2 = normalizeTableCellSelection(rng.cloneRange());
10923
-
10924
- // Insert end marker
10925
- if (!collapsed) {
10926
- rng2.collapse(false);
10927
- rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
10928
- }
10929
-
10930
- rng = normalizeTableCellSelection(rng);
10931
- rng.collapse(true);
10932
- rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
10933
- }
10934
-
10935
- selection.moveToBookmark({id: id, keep: 1});
10936
-
10937
- return {id: id};
10938
- };
10939
-
10940
- /**
10941
- * Restores the selection to the specified bookmark.
10942
- *
10943
- * @method moveToBookmark
10944
- * @param {Object} bookmark Bookmark to restore selection from.
10945
- * @return {Boolean} true/false if it was successful or not.
10946
- * @example
10947
- * // Stores a bookmark of the current selection
10948
- * var bm = tinymce.activeEditor.selection.getBookmark();
10949
- *
10950
- * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
10951
- *
10952
- * // Restore the selection bookmark
10953
- * tinymce.activeEditor.selection.moveToBookmark(bm);
10954
- */
10955
- this.moveToBookmark = function(bookmark) {
10956
- var rng, root, startContainer, endContainer, startOffset, endOffset;
10957
-
10958
- function setEndPoint(start) {
10959
- var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
10960
-
10961
- if (point) {
10962
- offset = point[0];
10963
-
10964
- // Find container node
10965
- for (node = root, i = point.length - 1; i >= 1; i--) {
10966
- children = node.childNodes;
10967
-
10968
- if (point[i] > children.length - 1) {
10969
- return;
10970
- }
10971
-
10972
- node = children[point[i]];
10973
- }
10974
-
10975
- // Move text offset to best suitable location
10976
- if (node.nodeType === 3) {
10977
- offset = Math.min(point[0], node.nodeValue.length);
10978
- }
10979
-
10980
- // Move element offset to best suitable location
10981
- if (node.nodeType === 1) {
10982
- offset = Math.min(point[0], node.childNodes.length);
10983
- }
10984
-
10985
- // Set offset within container node
10986
- if (start) {
10987
- rng.setStart(node, offset);
10988
- } else {
10989
- rng.setEnd(node, offset);
10990
- }
10991
- }
10992
-
10993
- return true;
10994
- }
10995
-
10996
- function restoreEndPoint(suffix) {
10997
- var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
10998
-
10999
- if (marker) {
11000
- node = marker.parentNode;
11001
-
11002
- if (suffix == 'start') {
11003
- if (!keep) {
11004
- idx = dom.nodeIndex(marker);
11005
- } else {
11006
- node = marker.firstChild;
11007
- idx = 1;
11008
- }
11009
-
11010
- startContainer = endContainer = node;
11011
- startOffset = endOffset = idx;
11012
- } else {
11013
- if (!keep) {
11014
- idx = dom.nodeIndex(marker);
11015
- } else {
11016
- node = marker.firstChild;
11017
- idx = 1;
11018
- }
11019
-
11020
- endContainer = node;
11021
- endOffset = idx;
11022
- }
11023
-
11024
- if (!keep) {
11025
- prev = marker.previousSibling;
11026
- next = marker.nextSibling;
11027
-
11028
- // Remove all marker text nodes
11029
- Tools.each(Tools.grep(marker.childNodes), function(node) {
11030
- if (node.nodeType == 3) {
11031
- node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
11032
- }
11033
- });
11034
-
11035
- // Remove marker but keep children if for example contents where inserted into the marker
11036
- // Also remove duplicated instances of the marker for example by a
11037
- // split operation or by WebKit auto split on paste feature
11038
- while ((marker = dom.get(bookmark.id + '_' + suffix))) {
11039
- dom.remove(marker, 1);
11040
- }
11041
-
11042
- // If siblings are text nodes then merge them unless it's Opera since it some how removes the node
11043
- // and we are sniffing since adding a lot of detection code for a browser with 3% of the market
11044
- // isn't worth the effort. Sorry, Opera but it's just a fact
11045
- if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
11046
- idx = prev.nodeValue.length;
11047
- prev.appendData(next.nodeValue);
11048
- dom.remove(next);
11049
-
11050
- if (suffix == 'start') {
11051
- startContainer = endContainer = prev;
11052
- startOffset = endOffset = idx;
11053
- } else {
11054
- endContainer = prev;
11055
- endOffset = idx;
11056
- }
11057
- }
11058
- }
11059
- }
11060
- }
11061
-
11062
- function addBogus(node) {
11063
- // Adds a bogus BR element for empty block elements
11064
- if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
11065
- node.innerHTML = '<br data-mce-bogus="1" />';
11066
- }
11067
-
11068
- return node;
11069
- }
11070
-
11071
- if (bookmark) {
11072
- if (bookmark.start) {
11073
- rng = dom.createRng();
11074
- root = dom.getRoot();
11075
-
11076
- if (selection.tridentSel) {
11077
- return selection.tridentSel.moveToBookmark(bookmark);
11078
- }
11079
-
11080
- if (setEndPoint(true) && setEndPoint()) {
11081
- selection.setRng(rng);
11082
- }
11083
- } else if (bookmark.id) {
11084
- // Restore start/end points
11085
- restoreEndPoint('start');
11086
- restoreEndPoint('end');
11087
-
11088
- if (startContainer) {
11089
- rng = dom.createRng();
11090
- rng.setStart(addBogus(startContainer), startOffset);
11091
- rng.setEnd(addBogus(endContainer), endOffset);
11092
- selection.setRng(rng);
11093
- }
11094
- } else if (bookmark.name) {
11095
- selection.select(dom.select(bookmark.name)[bookmark.index]);
11096
- } else if (bookmark.rng) {
11097
- selection.setRng(bookmark.rng);
11098
- }
11099
- }
11100
- };
11101
- }
11102
-
11103
- /**
11104
- * Returns true/false if the specified node is a bookmark node or not.
11105
- *
11106
- * @static
11107
- * @method isBookmarkNode
11108
- * @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
11109
- * @return {Boolean} true/false if the node is a bookmark node or not.
11110
- */
11111
- BookmarkManager.isBookmarkNode = function(node) {
11112
- return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
11113
- };
11114
-
11115
- return BookmarkManager;
10728
+ /**
10729
+ * BookmarkManager.js
10730
+ *
10731
+ * Copyright, Moxiecode Systems AB
10732
+ * Released under LGPL License.
10733
+ *
10734
+ * License: http://www.tinymce.com/license
10735
+ * Contributing: http://www.tinymce.com/contributing
10736
+ */
10737
+
10738
+ /**
10739
+ * This class handles selection bookmarks.
10740
+ *
10741
+ * @class tinymce.dom.BookmarkManager
10742
+ */
10743
+ define("tinymce/dom/BookmarkManager", [
10744
+ "tinymce/Env",
10745
+ "tinymce/util/Tools"
10746
+ ], function(Env, Tools) {
10747
+ /**
10748
+ * Constructs a new BookmarkManager instance for a specific selection instance.
10749
+ *
10750
+ * @constructor
10751
+ * @method BookmarkManager
10752
+ * @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
10753
+ */
10754
+ function BookmarkManager(selection) {
10755
+ var dom = selection.dom;
10756
+
10757
+ /**
10758
+ * Returns a bookmark location for the current selection. This bookmark object
10759
+ * can then be used to restore the selection after some content modification to the document.
10760
+ *
10761
+ * @method getBookmark
10762
+ * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
10763
+ * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
10764
+ * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
10765
+ * @example
10766
+ * // Stores a bookmark of the current selection
10767
+ * var bm = tinymce.activeEditor.selection.getBookmark();
10768
+ *
10769
+ * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
10770
+ *
10771
+ * // Restore the selection bookmark
10772
+ * tinymce.activeEditor.selection.moveToBookmark(bm);
10773
+ */
10774
+ this.getBookmark = function(type, normalized) {
10775
+ var rng, rng2, id, collapsed, name, element, chr = '&#xFEFF;', styles;
10776
+
10777
+ function findIndex(name, element) {
10778
+ var index = 0;
10779
+
10780
+ Tools.each(dom.select(name), function(node, i) {
10781
+ if (node == element) {
10782
+ index = i;
10783
+ }
10784
+ });
10785
+
10786
+ return index;
10787
+ }
10788
+
10789
+ function normalizeTableCellSelection(rng) {
10790
+ function moveEndPoint(start) {
10791
+ var container, offset, childNodes, prefix = start ? 'start' : 'end';
10792
+
10793
+ container = rng[prefix + 'Container'];
10794
+ offset = rng[prefix + 'Offset'];
10795
+
10796
+ if (container.nodeType == 1 && container.nodeName == "TR") {
10797
+ childNodes = container.childNodes;
10798
+ container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
10799
+ if (container) {
10800
+ offset = start ? 0 : container.childNodes.length;
10801
+ rng['set' + (start ? 'Start' : 'End')](container, offset);
10802
+ }
10803
+ }
10804
+ }
10805
+
10806
+ moveEndPoint(true);
10807
+ moveEndPoint();
10808
+
10809
+ return rng;
10810
+ }
10811
+
10812
+ function getLocation() {
10813
+ var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
10814
+
10815
+ function getPoint(rng, start) {
10816
+ var container = rng[start ? 'startContainer' : 'endContainer'],
10817
+ offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
10818
+
10819
+ if (container.nodeType == 3) {
10820
+ if (normalized) {
10821
+ for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
10822
+ offset += node.nodeValue.length;
10823
+ }
10824
+ }
10825
+
10826
+ point.push(offset);
10827
+ } else {
10828
+ childNodes = container.childNodes;
10829
+
10830
+ if (offset >= childNodes.length && childNodes.length) {
10831
+ after = 1;
10832
+ offset = Math.max(0, childNodes.length - 1);
10833
+ }
10834
+
10835
+ point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
10836
+ }
10837
+
10838
+ for (; container && container != root; container = container.parentNode) {
10839
+ point.push(dom.nodeIndex(container, normalized));
10840
+ }
10841
+
10842
+ return point;
10843
+ }
10844
+
10845
+ bookmark.start = getPoint(rng, true);
10846
+
10847
+ if (!selection.isCollapsed()) {
10848
+ bookmark.end = getPoint(rng);
10849
+ }
10850
+
10851
+ return bookmark;
10852
+ }
10853
+
10854
+ if (type == 2) {
10855
+ element = selection.getNode();
10856
+ name = element ? element.nodeName : null;
10857
+
10858
+ if (name == 'IMG') {
10859
+ return {name: name, index: findIndex(name, element)};
10860
+ }
10861
+
10862
+ if (selection.tridentSel) {
10863
+ return selection.tridentSel.getBookmark(type);
10864
+ }
10865
+
10866
+ return getLocation();
10867
+ }
10868
+
10869
+ // Handle simple range
10870
+ if (type) {
10871
+ return {rng: selection.getRng()};
10872
+ }
10873
+
10874
+ rng = selection.getRng();
10875
+ id = dom.uniqueId();
10876
+ collapsed = selection.isCollapsed();
10877
+ styles = 'overflow:hidden;line-height:0px';
10878
+
10879
+ // Explorer method
10880
+ if (rng.duplicate || rng.item) {
10881
+ // Text selection
10882
+ if (!rng.item) {
10883
+ rng2 = rng.duplicate();
10884
+
10885
+ try {
10886
+ // Insert start marker
10887
+ rng.collapse();
10888
+ rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
10889
+
10890
+ // Insert end marker
10891
+ if (!collapsed) {
10892
+ rng2.collapse(false);
10893
+
10894
+ // Detect the empty space after block elements in IE and move the
10895
+ // end back one character <p></p>] becomes <p>]</p>
10896
+ rng.moveToElementText(rng2.parentElement());
10897
+ if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
10898
+ rng2.move('character', -1);
10899
+ }
10900
+
10901
+ rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
10902
+ }
10903
+ } catch (ex) {
10904
+ // IE might throw unspecified error so lets ignore it
10905
+ return null;
10906
+ }
10907
+ } else {
10908
+ // Control selection
10909
+ element = rng.item(0);
10910
+ name = element.nodeName;
10911
+
10912
+ return {name: name, index: findIndex(name, element)};
10913
+ }
10914
+ } else {
10915
+ element = selection.getNode();
10916
+ name = element.nodeName;
10917
+ if (name == 'IMG') {
10918
+ return {name: name, index: findIndex(name, element)};
10919
+ }
10920
+
10921
+ // W3C method
10922
+ rng2 = normalizeTableCellSelection(rng.cloneRange());
10923
+
10924
+ // Insert end marker
10925
+ if (!collapsed) {
10926
+ rng2.collapse(false);
10927
+ rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
10928
+ }
10929
+
10930
+ rng = normalizeTableCellSelection(rng);
10931
+ rng.collapse(true);
10932
+ rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
10933
+ }
10934
+
10935
+ selection.moveToBookmark({id: id, keep: 1});
10936
+
10937
+ return {id: id};
10938
+ };
10939
+
10940
+ /**
10941
+ * Restores the selection to the specified bookmark.
10942
+ *
10943
+ * @method moveToBookmark
10944
+ * @param {Object} bookmark Bookmark to restore selection from.
10945
+ * @return {Boolean} true/false if it was successful or not.
10946
+ * @example
10947
+ * // Stores a bookmark of the current selection
10948
+ * var bm = tinymce.activeEditor.selection.getBookmark();
10949
+ *
10950
+ * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
10951
+ *
10952
+ * // Restore the selection bookmark
10953
+ * tinymce.activeEditor.selection.moveToBookmark(bm);
10954
+ */
10955
+ this.moveToBookmark = function(bookmark) {
10956
+ var rng, root, startContainer, endContainer, startOffset, endOffset;
10957
+
10958
+ function setEndPoint(start) {
10959
+ var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
10960
+
10961
+ if (point) {
10962
+ offset = point[0];
10963
+
10964
+ // Find container node
10965
+ for (node = root, i = point.length - 1; i >= 1; i--) {
10966
+ children = node.childNodes;
10967
+
10968
+ if (point[i] > children.length - 1) {
10969
+ return;
10970
+ }
10971
+
10972
+ node = children[point[i]];
10973
+ }
10974
+
10975
+ // Move text offset to best suitable location
10976
+ if (node.nodeType === 3) {
10977
+ offset = Math.min(point[0], node.nodeValue.length);
10978
+ }
10979
+
10980
+ // Move element offset to best suitable location
10981
+ if (node.nodeType === 1) {
10982
+ offset = Math.min(point[0], node.childNodes.length);
10983
+ }
10984
+
10985
+ // Set offset within container node
10986
+ if (start) {
10987
+ rng.setStart(node, offset);
10988
+ } else {
10989
+ rng.setEnd(node, offset);
10990
+ }
10991
+ }
10992
+
10993
+ return true;
10994
+ }
10995
+
10996
+ function restoreEndPoint(suffix) {
10997
+ var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
10998
+
10999
+ if (marker) {
11000
+ node = marker.parentNode;
11001
+
11002
+ if (suffix == 'start') {
11003
+ if (!keep) {
11004
+ idx = dom.nodeIndex(marker);
11005
+ } else {
11006
+ node = marker.firstChild;
11007
+ idx = 1;
11008
+ }
11009
+
11010
+ startContainer = endContainer = node;
11011
+ startOffset = endOffset = idx;
11012
+ } else {
11013
+ if (!keep) {
11014
+ idx = dom.nodeIndex(marker);
11015
+ } else {
11016
+ node = marker.firstChild;
11017
+ idx = 1;
11018
+ }
11019
+
11020
+ endContainer = node;
11021
+ endOffset = idx;
11022
+ }
11023
+
11024
+ if (!keep) {
11025
+ prev = marker.previousSibling;
11026
+ next = marker.nextSibling;
11027
+
11028
+ // Remove all marker text nodes
11029
+ Tools.each(Tools.grep(marker.childNodes), function(node) {
11030
+ if (node.nodeType == 3) {
11031
+ node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
11032
+ }
11033
+ });
11034
+
11035
+ // Remove marker but keep children if for example contents where inserted into the marker
11036
+ // Also remove duplicated instances of the marker for example by a
11037
+ // split operation or by WebKit auto split on paste feature
11038
+ while ((marker = dom.get(bookmark.id + '_' + suffix))) {
11039
+ dom.remove(marker, 1);
11040
+ }
11041
+
11042
+ // If siblings are text nodes then merge them unless it's Opera since it some how removes the node
11043
+ // and we are sniffing since adding a lot of detection code for a browser with 3% of the market
11044
+ // isn't worth the effort. Sorry, Opera but it's just a fact
11045
+ if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
11046
+ idx = prev.nodeValue.length;
11047
+ prev.appendData(next.nodeValue);
11048
+ dom.remove(next);
11049
+
11050
+ if (suffix == 'start') {
11051
+ startContainer = endContainer = prev;
11052
+ startOffset = endOffset = idx;
11053
+ } else {
11054
+ endContainer = prev;
11055
+ endOffset = idx;
11056
+ }
11057
+ }
11058
+ }
11059
+ }
11060
+ }
11061
+
11062
+ function addBogus(node) {
11063
+ // Adds a bogus BR element for empty block elements
11064
+ if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
11065
+ node.innerHTML = '<br data-mce-bogus="1" />';
11066
+ }
11067
+
11068
+ return node;
11069
+ }
11070
+
11071
+ if (bookmark) {
11072
+ if (bookmark.start) {
11073
+ rng = dom.createRng();
11074
+ root = dom.getRoot();
11075
+
11076
+ if (selection.tridentSel) {
11077
+ return selection.tridentSel.moveToBookmark(bookmark);
11078
+ }
11079
+
11080
+ if (setEndPoint(true) && setEndPoint()) {
11081
+ selection.setRng(rng);
11082
+ }
11083
+ } else if (bookmark.id) {
11084
+ // Restore start/end points
11085
+ restoreEndPoint('start');
11086
+ restoreEndPoint('end');
11087
+
11088
+ if (startContainer) {
11089
+ rng = dom.createRng();
11090
+ rng.setStart(addBogus(startContainer), startOffset);
11091
+ rng.setEnd(addBogus(endContainer), endOffset);
11092
+ selection.setRng(rng);
11093
+ }
11094
+ } else if (bookmark.name) {
11095
+ selection.select(dom.select(bookmark.name)[bookmark.index]);
11096
+ } else if (bookmark.rng) {
11097
+ selection.setRng(bookmark.rng);
11098
+ }
11099
+ }
11100
+ };
11101
+ }
11102
+
11103
+ /**
11104
+ * Returns true/false if the specified node is a bookmark node or not.
11105
+ *
11106
+ * @static
11107
+ * @method isBookmarkNode
11108
+ * @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
11109
+ * @return {Boolean} true/false if the node is a bookmark node or not.
11110
+ */
11111
+ BookmarkManager.isBookmarkNode = function(node) {
11112
+ return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
11113
+ };
11114
+
11115
+ return BookmarkManager;
11116
11116
  });
11117
11117
 
11118
11118
  // Included from: js/tinymce/classes/dom/Selection.js