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