editor_plugin_src.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /**
  2. * editor_plugin_src.js
  3. *
  4. * Copyright 2009, Moxiecode Systems AB
  5. * Released under LGPL License.
  6. *
  7. * License: http://tinymce.moxiecode.com/license
  8. * Contributing: http://tinymce.moxiecode.com/contributing
  9. */
  10. (function() {
  11. function findParentLayer(node) {
  12. do {
  13. if (node.className && node.className.indexOf('mceItemLayer') != -1) {
  14. return node;
  15. }
  16. } while (node = node.parentNode);
  17. };
  18. tinymce.create('tinymce.plugins.Layer', {
  19. init : function(ed, url) {
  20. var t = this;
  21. t.editor = ed;
  22. // Register commands
  23. ed.addCommand('mceInsertLayer', t._insertLayer, t);
  24. ed.addCommand('mceMoveForward', function() {
  25. t._move(1);
  26. });
  27. ed.addCommand('mceMoveBackward', function() {
  28. t._move(-1);
  29. });
  30. ed.addCommand('mceMakeAbsolute', function() {
  31. t._toggleAbsolute();
  32. });
  33. // Register buttons
  34. ed.addButton('moveforward', {title : 'layer.forward_desc', cmd : 'mceMoveForward'});
  35. ed.addButton('movebackward', {title : 'layer.backward_desc', cmd : 'mceMoveBackward'});
  36. ed.addButton('absolute', {title : 'layer.absolute_desc', cmd : 'mceMakeAbsolute'});
  37. ed.addButton('insertlayer', {title : 'layer.insertlayer_desc', cmd : 'mceInsertLayer'});
  38. ed.onInit.add(function() {
  39. var dom = ed.dom;
  40. if (tinymce.isIE)
  41. ed.getDoc().execCommand('2D-Position', false, true);
  42. });
  43. // Remove serialized styles when selecting a layer since it might be changed by a drag operation
  44. ed.onMouseUp.add(function(ed, e) {
  45. var layer = findParentLayer(e.target);
  46. if (layer) {
  47. ed.dom.setAttrib(layer, 'data-mce-style', '');
  48. }
  49. });
  50. // Fixes edit focus issues with layers on Gecko
  51. // This will enable designMode while inside a layer and disable it when outside
  52. ed.onMouseDown.add(function(ed, e) {
  53. var node = e.target, doc = ed.getDoc(), parent;
  54. if (tinymce.isGecko) {
  55. if (findParentLayer(node)) {
  56. if (doc.designMode !== 'on') {
  57. doc.designMode = 'on';
  58. // Repaint caret
  59. node = doc.body;
  60. parent = node.parentNode;
  61. parent.removeChild(node);
  62. parent.appendChild(node);
  63. }
  64. } else if (doc.designMode == 'on') {
  65. doc.designMode = 'off';
  66. }
  67. }
  68. });
  69. ed.onNodeChange.add(t._nodeChange, t);
  70. ed.onVisualAid.add(t._visualAid, t);
  71. },
  72. getInfo : function() {
  73. return {
  74. longname : 'Layer',
  75. author : 'Moxiecode Systems AB',
  76. authorurl : 'http://tinymce.moxiecode.com',
  77. infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',
  78. version : tinymce.majorVersion + "." + tinymce.minorVersion
  79. };
  80. },
  81. // Private methods
  82. _nodeChange : function(ed, cm, n) {
  83. var le, p;
  84. le = this._getParentLayer(n);
  85. p = ed.dom.getParent(n, 'DIV,P,IMG');
  86. if (!p) {
  87. cm.setDisabled('absolute', 1);
  88. cm.setDisabled('moveforward', 1);
  89. cm.setDisabled('movebackward', 1);
  90. } else {
  91. cm.setDisabled('absolute', 0);
  92. cm.setDisabled('moveforward', !le);
  93. cm.setDisabled('movebackward', !le);
  94. cm.setActive('absolute', le && le.style.position.toLowerCase() == "absolute");
  95. }
  96. },
  97. // Private methods
  98. _visualAid : function(ed, e, s) {
  99. var dom = ed.dom;
  100. tinymce.each(dom.select('div,p', e), function(e) {
  101. if (/^(absolute|relative|fixed)$/i.test(e.style.position)) {
  102. if (s)
  103. dom.addClass(e, 'mceItemVisualAid');
  104. else
  105. dom.removeClass(e, 'mceItemVisualAid');
  106. dom.addClass(e, 'mceItemLayer');
  107. }
  108. });
  109. },
  110. _move : function(d) {
  111. var ed = this.editor, i, z = [], le = this._getParentLayer(ed.selection.getNode()), ci = -1, fi = -1, nl;
  112. nl = [];
  113. tinymce.walk(ed.getBody(), function(n) {
  114. if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position))
  115. nl.push(n);
  116. }, 'childNodes');
  117. // Find z-indexes
  118. for (i=0; i<nl.length; i++) {
  119. z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex) : 0;
  120. if (ci < 0 && nl[i] == le)
  121. ci = i;
  122. }
  123. if (d < 0) {
  124. // Move back
  125. // Try find a lower one
  126. for (i=0; i<z.length; i++) {
  127. if (z[i] < z[ci]) {
  128. fi = i;
  129. break;
  130. }
  131. }
  132. if (fi > -1) {
  133. nl[ci].style.zIndex = z[fi];
  134. nl[fi].style.zIndex = z[ci];
  135. } else {
  136. if (z[ci] > 0)
  137. nl[ci].style.zIndex = z[ci] - 1;
  138. }
  139. } else {
  140. // Move forward
  141. // Try find a higher one
  142. for (i=0; i<z.length; i++) {
  143. if (z[i] > z[ci]) {
  144. fi = i;
  145. break;
  146. }
  147. }
  148. if (fi > -1) {
  149. nl[ci].style.zIndex = z[fi];
  150. nl[fi].style.zIndex = z[ci];
  151. } else
  152. nl[ci].style.zIndex = z[ci] + 1;
  153. }
  154. ed.execCommand('mceRepaint');
  155. },
  156. _getParentLayer : function(n) {
  157. return this.editor.dom.getParent(n, function(n) {
  158. return n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position);
  159. });
  160. },
  161. _insertLayer : function() {
  162. var ed = this.editor, dom = ed.dom, p = dom.getPos(dom.getParent(ed.selection.getNode(), '*')), body = ed.getBody();
  163. ed.dom.add(body, 'div', {
  164. style : {
  165. position : 'absolute',
  166. left : p.x,
  167. top : (p.y > 20 ? p.y : 20),
  168. width : 100,
  169. height : 100
  170. },
  171. 'class' : 'mceItemVisualAid mceItemLayer'
  172. }, ed.selection.getContent() || ed.getLang('layer.content'));
  173. // Workaround for IE where it messes up the JS engine if you insert a layer on IE 6,7
  174. if (tinymce.isIE)
  175. dom.setHTML(body, body.innerHTML);
  176. },
  177. _toggleAbsolute : function() {
  178. var ed = this.editor, le = this._getParentLayer(ed.selection.getNode());
  179. if (!le)
  180. le = ed.dom.getParent(ed.selection.getNode(), 'DIV,P,IMG');
  181. if (le) {
  182. if (le.style.position.toLowerCase() == "absolute") {
  183. ed.dom.setStyles(le, {
  184. position : '',
  185. left : '',
  186. top : '',
  187. width : '',
  188. height : ''
  189. });
  190. ed.dom.removeClass(le, 'mceItemVisualAid');
  191. ed.dom.removeClass(le, 'mceItemLayer');
  192. } else {
  193. if (le.style.left == "")
  194. le.style.left = 20 + 'px';
  195. if (le.style.top == "")
  196. le.style.top = 20 + 'px';
  197. if (le.style.width == "")
  198. le.style.width = le.width ? (le.width + 'px') : '100px';
  199. if (le.style.height == "")
  200. le.style.height = le.height ? (le.height + 'px') : '100px';
  201. le.style.position = "absolute";
  202. ed.dom.setAttrib(le, 'data-mce-style', '');
  203. ed.addVisual(ed.getBody());
  204. }
  205. ed.execCommand('mceRepaint');
  206. ed.nodeChanged();
  207. }
  208. }
  209. });
  210. // Register plugin
  211. tinymce.PluginManager.add('layer', tinymce.plugins.Layer);
  212. })();