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 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