Rev 8231 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8231 | Rev 9054 | ||
---|---|---|---|
Line 5... | Line 5... | ||
5 | //editor.init(textareaelement, optional callback on loaded) |
5 | //editor.init(textareaelement, optional callback on loaded) |
6 | function speckInit(callback) { |
6 | function speckInit(callback) { |
7 | var tas = document.getElementsByTagName("textarea"); |
7 | var tas = document.getElementsByTagName("textarea"); |
8 | var found = false; |
8 | var found = false; |
9 | for(i=0;i<tas.length;i++) { |
9 | for(i=0;i<tas.length;i++) { |
10 |
|
10 | var ta = tas[i]; |
11 |
|
11 | if (ta.className == "iEdit") { |
12 |
|
12 | var editor = new speckEditor(); |
13 |
|
13 | editor.init(ta, callback); |
14 |
|
14 | found = true; |
15 |
|
15 | } |
16 | } |
16 | } |
17 | if (!found) { |
17 | if (!found) { |
18 | if (callback) |
18 | if (callback) |
19 | callback.call(); |
19 | callback.call(); |
20 | } |
20 | } |
21 |
|
21 | return true; |
22 | }; |
22 | }; |
23 | 23 | ||
24 | //Be sure to call speckClose if you are hiding or removing a speck edit |
24 | //Be sure to call speckClose if you are hiding or removing a speck edit |
25 | //from the screen and plan to open another before refreshing the page. |
25 | //from the screen and plan to open another before refreshing the page. |
26 | function speckClose() { |
26 | function speckClose() { |
27 | for(var i in iEdit) |
27 | for(var i in iEdit) |
28 | { |
28 | { |
29 | iEdit[i].iframe.contentWindow.document.designMode = "off"; |
29 | iEdit[i].iframe.contentWindow.document.designMode = "off"; |
- | 30 | } |
|
- | 31 | }; |
|
- | 32 | ||
- | 33 | /** (re)Opens all specks **/ |
|
- | 34 | function speckOpen() { |
|
- | 35 | for(var i in iEdit) |
|
- | 36 | { |
|
- | 37 | iEdit[i].iframe.contentWindow.document.designMode = "on"; |
|
- | 38 | } |
|
- | 39 | }; |
|
- | 40 | ||
- | 41 | /** Toggle Html Editor on all specks */ |
|
- | 42 | function speckToggleAll() { |
|
- | 43 | for(var i in iEdit) |
|
- | 44 | { |
|
- | 45 | iEdit[i].toggleMode(); |
|
30 | } |
46 | } |
31 | }; |
47 | }; |
32 | 48 | ||
33 | //Collection of all text windows: accessible by: |
49 | //Collection of all text windows: accessible by: |
34 | //iEdit[TextAreaId].html(); |
50 | //iEdit[TextAreaId].html(); |
Line 94... | Line 110... | ||
94 | ], |
110 | ], |
95 | 111 | ||
96 | //Initialize the edit window |
112 | //Initialize the edit window |
97 | init: function(ta, callback) { |
113 | init: function(ta, callback) { |
98 | 114 | ||
99 |
|
115 | this.ta = ta; |
100 | this.id = ta.id; |
116 | this.id = ta.id; |
101 | iEdit[this.id] = this; |
117 | iEdit[this.id] = this; |
102 | 118 | ||
103 |
|
119 | if (callback) |
104 |
|
120 | this.loaded = callback; |
105 | 121 | ||
106 | //Get the current width |
122 | //Get the current width |
107 | this.width = this.ta.offsetWidth; |
123 | this.width = this.ta.offsetWidth; |
108 | if (this.width == 0) |
124 | if (this.width == 0) |
109 |
|
125 | this.width = parseInt(this.ta.style.width); |
110 | 126 | ||
111 | //Get the current height |
127 | //Get the current height |
112 | this.height = this.ta.offsetHeight; |
128 | this.height = this.ta.offsetHeight; |
113 | if (this.height == 0) |
129 | if (this.height == 0) |
114 |
|
130 | this.height = parseInt(this.ta.style.height); |
115 | 131 | ||
116 | this.ta.style.display = "none"; |
132 | this.ta.style.display = "none"; |
117 | 133 | ||
118 |
|
134 | this.container = this.$new("div"); |
119 | 135 | ||
120 |
|
136 | this.tb = this.$new("div"); |
121 |
|
137 | this.tb.className = "speckToolbar"; |
122 | this.tb.style.width = this.width + "px"; |
138 | this.tb.style.width = this.width + "px"; |
123 | this.container.appendChild(this.tb); |
139 | this.container.appendChild(this.tb); |
124 | 140 | ||
125 | //Add the features |
141 | //Add the features |
126 |
|
142 | for(var i=0;i<this.features.length;i+=2) { |
127 |
|
143 | this.addFeature(this.features[i], this.features[i+1]); |
128 |
|
144 | } |
129 | 145 | ||
130 | this.ta.style.height = (this.height-32) + "px"; |
146 | this.ta.style.height = (this.height-32) + "px"; |
131 | this.ta.parentNode.replaceChild(this.container, this.ta); |
147 | this.ta.parentNode.replaceChild(this.container, this.ta); |
132 |
|
148 | this.container.appendChild(this.ta); |
133 | 149 | ||
134 | this.initEdit(); |
150 | this.initEdit(); |
135 | 151 | ||
136 | }, |
152 | }, |
137 | initEdit: function(content) { |
153 | initEdit: function(content) { |
Line 148... | Line 164... | ||
148 | 164 | ||
149 | //Save style properties with property called savestyle |
165 | //Save style properties with property called savestyle |
150 | content = this.ta.value.replace(/(style|STYLE|Style)=('|").+?('|")/g, function(match){ return match + " save" + match; }); |
166 | content = this.ta.value.replace(/(style|STYLE|Style)=('|").+?('|")/g, function(match){ return match + " save" + match; }); |
151 | 167 | ||
152 | //Write out current content to the iframe window, include edit mode stylesheet |
168 | //Write out current content to the iframe window, include edit mode stylesheet |
153 |
|
169 | this.iframe.contentWindow.document.open(); |
154 |
|
170 | //this.iframe.contentWindow.document.write("<html><head><link id='ThemeStyle' href='" + this.editStylePath + "' type='text/css' rel='stylesheet' /></head><body style='background:#fff url();color:#000;'>" + content + "</body></html>"); |
155 |
|
171 | this.iframe.contentWindow.document.write("<html><head></head><body style='background:#fff url();color:#000;'>" + content + "</body></html>"); |
156 |
|
172 | this.iframe.contentWindow.document.close(); |
157 | 173 | ||
158 | this.enterDesignMode(); |
174 | this.enterDesignMode(); |
159 | 175 | ||
160 |
|
176 | return true; |
161 | }, |
177 | }, |
162 | enterDesignMode: function() { |
178 | enterDesignMode: function() { |
163 | 179 | ||
164 | //Firefox needs a little time for this. |
180 | //Firefox needs a little time for this. |
165 | if (!this.iframe.contentWindow.document.body) { |
181 | if (!this.iframe.contentWindow.document.body) { |
166 | var self = this; |
182 | var self = this; |
167 |
|
183 | setTimeout(function() { self.enterDesignMode(); }, 1); |
168 |
|
184 | return; |
169 |
|
185 | } |
170 | 186 | ||
171 |
|
187 | //Turn on design mode |
172 |
|
188 | this.iframe.contentWindow.document.designMode = "on"; |
173 | 189 | ||
174 |
|
190 | this.wysiwyg = true; |
175 | 191 | ||
176 | //call loaded event |
192 | //call loaded event |
177 | if (this.loaded) |
193 | if (this.loaded) |
178 | this.loaded.call(); |
194 | this.loaded.call(); |
179 | }, |
195 | }, |
180 | addFeature: function(action, text) { |
196 | addFeature: function(action, text) { |
181 | switch (action) { |
197 | switch (action) { |
182 | case "formatblock": |
198 | case "formatblock": |
183 |
|
199 | this.hBar = this.$new("div"); |
184 |
|
200 | this.hBar.id = this.id + "Hbar"; |
185 | this.addBar(this.hBar, "formatblock", this.blockOptions, text); |
201 | this.addBar(this.hBar, "formatblock", this.blockOptions, text); |
186 | this.container.appendChild(this.hBar); |
202 | this.container.appendChild(this.hBar); |
187 | break; |
203 | break; |
188 | case "fontname": |
204 | case "fontname": |
189 |
|
205 | this.fBar = this.$new("div"); |
190 |
|
206 | this.fBar.id = this.id + "Fbar"; |
191 | this.addBar(this.fBar, "fontname", this.fontOptions, text); |
207 | this.addBar(this.fBar, "fontname", this.fontOptions, text); |
192 | this.container.appendChild(this.fBar); |
208 | this.container.appendChild(this.fBar); |
193 | break; |
209 | break; |
194 | case "fontsize": |
210 | case "fontsize": |
195 |
|
211 | this.sBar = this.$new("div"); |
196 |
|
212 | this.sBar.id = this.id + "Sbar"; |
197 | this.addBar(this.sBar, "fontsize", this.fontSizes, text); |
213 | this.addBar(this.sBar, "fontsize", this.fontSizes, text); |
198 | this.container.appendChild(this.sBar); |
214 | this.container.appendChild(this.sBar); |
199 | break; |
215 | break; |
200 | case "forecolor": |
216 | case "forecolor": |
201 | this.addColor("forecolor", this.colors, text); |
217 | this.addColor("forecolor", this.colors, text); |
202 | this.container.appendChild(this.cBar); |
218 | this.container.appendChild(this.cBar); |
203 | break; |
219 | break; |
204 | case "link": |
220 | case "link": |
205 | this.addLinkBar("link", text); |
221 | this.addLinkBar("link", text); |
206 | this.container.appendChild(this.lBar); |
222 | this.container.appendChild(this.lBar); |
207 | break; |
223 | break; |
208 | default: |
224 | default: |
209 | this.tb.appendChild(this.getButton(action, text)); |
225 | this.tb.appendChild(this.getButton(action, text)); |
210 | break; |
226 | break; |
211 | } |
227 | } |
212 | }, |
228 | }, |
213 | getButton: function(action, text) { |
229 | getButton: function(action, text) { |
214 | var self = this; |
230 | var self = this; |
215 | 231 | ||
216 | var button = this.$new("input"); |
232 | var button = this.$new("input"); |
217 | button.type = "button"; |
233 | button.type = "button"; |
218 | button.id = action + "Button"; |
234 | button.id = action + "Button"; |
219 | button.title = text; |
235 | button.title = text; |
220 | button.className = "speckButton"; |
236 | button.className = "speckButton"; |
221 | button.action = action; |
237 | button.action = action; |
222 | button.onclick = function() { self.execCommand(this); }; |
238 | button.onclick = function() { self.execCommand(this); }; |
223 | return button; |
239 | return button; |
224 | }, |
240 | }, |
225 | addColor: function(action, options, text) { |
241 | addColor: function(action, options, text) { |
226 | 242 | ||
227 |
|
243 | var button = this.getButton(action, text); // this.$new("input"); |
228 | var self = this; |
244 | var self = this; |
229 | button.onclick = function() { self.showSelect(this); }; |
245 | button.onclick = function() { self.showSelect(this); }; |
230 | 246 | ||
231 |
|
247 | var bar = this.$new("div"); |
232 |
|
248 | bar.id = action + "Select"; |
233 |
|
249 | bar.className = "speckColorBar"; |
234 | bar.style.width = (this.width - 2) + "px"; //2 is border width |
250 | bar.style.width = (this.width - 2) + "px"; //2 is border width |
235 | bar.style.display = "none"; |
251 | bar.style.display = "none"; |
236 |
|
252 | for (var i=0;i<options.length;i++) |
237 |
|
253 | { |
238 |
|
254 | var option = this.$new("input"); |
239 |
|
255 | option.val = options[i]; |
240 |
|
256 | option.type = "button"; |
241 |
|
257 | option.style.backgroundColor = "#" + option.val; |
242 |
|
258 | option.action = action; |
243 |
|
259 | option.className = "speckColor"; |
244 | option.onclick = function() { self.execCommand(this); }; |
260 | option.onclick = function() { self.execCommand(this); }; |
245 | 261 | ||
246 |
|
262 | bar.appendChild(option); |
247 |
|
263 | } |
248 |
|
264 | this.cBar = bar; |
249 | button.selectMenuId = bar.id; |
265 | button.selectMenuId = bar.id; |
250 | this.tb.appendChild(button); |
266 | this.tb.appendChild(button); |
251 |
|
267 | return true; |
252 | }, |
268 | }, |
253 | addLinkBar: function(action, text) { |
269 | addLinkBar: function(action, text) { |
254 |
|
270 | var button = this.getButton(action, text); //this.$new("input"); |
255 | 271 | ||
256 | var self = this; |
272 | var self = this; |
257 | button.onclick = function() { self.showSelect(this); }; |
273 | button.onclick = function() { self.showSelect(this); }; |
258 | 274 | ||
259 |
|
275 | var bar = this.$new("div"); |
260 |
|
276 | bar.id = action + "linkbar"; |
261 |
|
277 | bar.className = "speckLinkbar"; |
262 | bar.style.width = (this.width-2) + "px"; //2 is border width |
278 | bar.style.width = (this.width-2) + "px"; //2 is border width |
263 | bar.style.display = "none"; |
279 | bar.style.display = "none"; |
264 | 280 | ||
265 |
|
281 | this.linkUrl = this.$new("input"); |
266 |
|
282 | this.linkUrl.id = this.id + "link"; |
267 | this.linkUrl.style.width = (this.width - 60) + "px"; |
283 | this.linkUrl.style.width = (this.width - 60) + "px"; |
268 | this.linkUrl.value = "http://"; |
284 | this.linkUrl.value = "http://"; |
269 | 285 | ||
270 | var link = this.$new("input"); |
286 | var link = this.$new("input"); |
271 | link.type = "button"; |
287 | link.type = "button"; |
272 | link.id = "linkingButton"; |
288 | link.id = "linkingButton"; |
273 | link.value = "link"; |
289 | link.value = "link"; |
274 | link.className = "linkbarButton"; |
290 | link.className = "linkbarButton"; |
275 | link.action = "createlink"; |
291 | link.action = "createlink"; |
276 | link.onclick = function() { self.execCommand(this) }; |
292 | link.onclick = function() { self.execCommand(this) }; |
277 | bar.appendChild(this.linkUrl); |
293 | bar.appendChild(this.linkUrl); |
278 | bar.appendChild(link); |
294 | bar.appendChild(link); |
279 | 295 | ||
280 |
|
296 | this.lBar = bar; |
281 | button.selectMenuId = bar.id; |
297 | button.selectMenuId = bar.id; |
282 | this.tb.appendChild(button); |
298 | this.tb.appendChild(button); |
283 |
|
299 | return true; |
284 | }, |
300 | }, |
285 | addBar: function(bar, action, options, text) { |
301 | addBar: function(bar, action, options, text) { |
286 |
|
302 | var button = this.getButton(action, text); //this.$new("input"); |
287 | var self = this; |
303 | var self = this; |
288 | button.onclick = function() { self.showSelect(this); }; |
304 | button.onclick = function() { self.showSelect(this); }; |
289 | 305 | ||
290 |
|
306 | bar.className = "speckBar"; |
291 | bar.style.width = (this.width-2) + "px"; |
307 | bar.style.width = (this.width-2) + "px"; |
292 | bar.style.display = "none"; |
308 | bar.style.display = "none"; |
293 | 309 | ||
294 |
|
310 | for (var i=0;i<options.length;i+=2) |
295 |
|
311 | { |
296 |
|
312 | var option = this.$new("input"); |
297 |
|
313 | option.val = options[i]; |
298 |
|
314 | option.value = options[i + 1]; |
299 |
|
315 | option.type = "button"; |
300 |
|
316 | option.action = action; |
301 |
|
317 | option.editor = this.id; |
302 |
|
318 | option.className = "speckOption"; |
303 | option.onclick = function() { self.execCommand(this) }; |
319 | option.onclick = function() { self.execCommand(this) }; |
304 | 320 | ||
305 |
|
321 | bar.appendChild(option); |
306 |
|
322 | } |
307 | button.selectMenuId = bar.id; |
323 | button.selectMenuId = bar.id; |
308 | this.tb.appendChild(button); |
324 | this.tb.appendChild(button); |
309 |
|
325 | return true; |
310 | }, |
326 | }, |
311 | hideSelects: function() { |
327 | hideSelects: function() { |
312 | var buttons = this.tb.childNodes; |
328 | var buttons = this.tb.childNodes; |
313 | for(var i=0;i<buttons.length;i++) { |
329 | for(var i=0;i<buttons.length;i++) { |
314 | var button = buttons[i]; |
330 | var button = buttons[i]; |
Line 320... | Line 336... | ||
320 | this.lBar.style.display = "none"; |
336 | this.lBar.style.display = "none"; |
321 | this.iframe.style.height = (this.height-32) + "px"; |
337 | this.iframe.style.height = (this.height-32) + "px"; |
322 | this.ta.style.height = (this.height-32) + "px"; |
338 | this.ta.style.height = (this.height-32) + "px"; |
323 | }, |
339 | }, |
324 | addLinkbar: function() { |
340 | addLinkbar: function() { |
325 |
|
341 | this.lBar = this.$new("div"); |
326 |
|
342 | this.lBar.id = this.id + "linkbar"; |
327 |
|
343 | this.lBar.className = "speckLinkbar"; |
328 | this.lBar.style.width = this.width-10 + "px"; |
344 | this.lBar.style.width = this.width-10 + "px"; |
329 | this.lBar.style.display = "none"; |
345 | this.lBar.style.display = "none"; |
330 | 346 | ||
331 |
|
347 | this.linkUrl = this.$new("input"); |
332 |
|
348 | this.linkUrl.id = this.id + "link"; |
333 | this.linkUrl.style.width = (this.width - 60) + "px"; |
349 | this.linkUrl.style.width = (this.width - 60) + "px"; |
334 | this.linkUrl.value = "http://"; |
350 | this.linkUrl.value = "http://"; |
335 | 351 | ||
336 | var link = this.$new("input"); |
352 | var link = this.$new("input"); |
337 | link.type = "button"; |
353 | link.type = "button"; |
Line 351... | Line 367... | ||
351 | this.lBar.style.display = "none"; |
367 | this.lBar.style.display = "none"; |
352 | this.iframe.style.height = (this.height-32) + "px"; |
368 | this.iframe.style.height = (this.height-32) + "px"; |
353 | } |
369 | } |
354 | }, |
370 | }, |
355 | setFocus: function() { |
371 | setFocus: function() { |
356 |
|
372 | if (this.wysiwyg == true) |
357 |
|
373 | this.iframe.contentWindow.focus(); |
358 |
|
374 | else |
359 |
|
375 | this.ta.focus(); |
360 | }, |
376 | }, |
361 | toggleMode: function() { |
377 | toggleMode: function() { |
362 | this.hideSelects(); |
378 | this.hideSelects(); |
363 | if (this.wysiwyg) { |
379 | if (this.wysiwyg) { |
364 | this.html(); //update html |
380 | this.html(); //update html |
Line 366... | Line 382... | ||
366 | this.iframe.style.display = "none"; |
382 | this.iframe.style.display = "none"; |
367 | this.wysiwyg = false; |
383 | this.wysiwyg = false; |
368 | } |
384 | } |
369 | else { |
385 | else { |
370 | this.ta.style.display = "none"; |
386 | this.ta.style.display = "none"; |
371 | this.initEdit(this.ta.value); |
387 | this.initEdit(this.ta.value); |
- | 388 | this.wysiwyg = true; |
|
- | 389 | } |
|
- | 390 | }, |
|
- | 391 | disable: function() { |
|
- | 392 | this.hideSelects(); |
|
- | 393 | if (this.wysiwyg) { |
|
- | 394 | this.html(); //update html |
|
- | 395 | this.ta.style.display = "block"; |
|
- | 396 | this.iframe.style.display = "none"; |
|
- | 397 | this.wysiwyg = false; |
|
- | 398 | } |
|
- | 399 | }, |
|
- | 400 | enable: function() { |
|
- | 401 | this.hideSelects(); |
|
- | 402 | if (!this.wysiwyg) { |
|
- | 403 | this.ta.style.display = "none"; |
|
- | 404 | this.initEdit(this.ta.value); |
|
372 | this.wysiwyg = true; |
405 | this.wysiwyg = true; |
373 | } |
406 | } |
374 | }, |
407 | }, |
375 | html: function() { |
408 | html: function() { |
376 | this.ta.value = this.innerXML(this.iframe.contentWindow.document.body.cloneNode(true)); |
409 | this.ta.value = this.innerXML(this.iframe.contentWindow.document.body.cloneNode(true)); |
377 | return this.ta.value; |
410 | return this.ta.value; |
378 | }, |
411 | }, |
379 | showSelect: function(selector) { |
412 | showSelect: function(selector) { |
380 | 413 | ||
381 | var selectMenu = document.getElementById(selector.selectMenuId); |
414 | var selectMenu = document.getElementById(selector.selectMenuId); |
382 | 415 | ||
383 | //if select bar is already open, close it. |
416 | //if select bar is already open, close it. |
384 | if (selectMenu.style.display == "block") { |
417 | if (selectMenu.style.display == "block") { |
385 | this.hideSelects(); |
418 | this.hideSelects(); |
Line 393... | Line 426... | ||
393 | }, |
426 | }, |
394 | execCommand: function(button) { |
427 | execCommand: function(button) { |
395 | 428 | ||
396 | var doc = this.iframe.contentWindow.document; |
429 | var doc = this.iframe.contentWindow.document; |
397 | 430 | ||
398 |
|
431 | switch (button.action) { |
399 |
|
432 | case "createlink": |
400 |
|
433 | if (this.linkUrl.value != "") { |
401 | doc.execCommand(button.action, false, this.linkUrl.value); |
434 | doc.execCommand(button.action, false, this.linkUrl.value); |
402 | this.toggleLinkbar(); |
435 | this.toggleLinkbar(); |
403 | } |
436 | } |
404 | break; |
437 | break; |
405 |
|
438 | case "formatblock": |
406 |
|
439 | case "fontsize": |
407 |
|
440 | case "forecolor": |
408 |
|
441 | case "fontname": |
409 |
|
442 | doc.execCommand(button.action, false, button.val); |
410 | break; |
443 | break; |
411 | case "link": |
444 | case "link": |
412 | this.toggleLinkbar(); |
445 | this.toggleLinkbar(); |
413 | break; |
446 | break; |
414 | case "html": |
447 | case "html": |
415 | this.toggleMode(); |
448 | this.toggleMode(); |
416 | break; |
449 | break; |
417 |
|
450 | default: |
418 |
|
451 | doc.execCommand(button.action, false, null); |
419 | break; |
452 | break; |
420 | } |
453 | } |
421 | 454 | ||
422 | if (button.parentNode.className == "speckSelect") { |
455 | if (button.parentNode.className == "speckSelect") { |
423 | button.parentNode.style.display = "none"; |
456 | button.parentNode.style.display = "none"; |