plugin.js 5.0 KB

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