Chris@76
|
1 // *** smc_Editor class.
|
Chris@76
|
2 function smc_Editor(oOptions)
|
Chris@76
|
3 {
|
Chris@76
|
4 this.opt = oOptions;
|
Chris@76
|
5
|
Chris@76
|
6 // Create some links to the editor object.
|
Chris@76
|
7 this.oTextHandle = null;
|
Chris@76
|
8 this.sCurrentText = 'sText' in this.opt ? this.opt.sText : '';
|
Chris@76
|
9
|
Chris@76
|
10 // How big?
|
Chris@76
|
11 this.sEditWidth = 'sEditWidth' in this.opt ? this.opt.sEditWidth : '70%';
|
Chris@76
|
12 this.sEditHeight = 'sEditHeight' in this.opt ? this.opt.sEditHeight : '150px';
|
Chris@76
|
13
|
Chris@76
|
14 this.showDebug = false;
|
Chris@76
|
15 this.bRichTextEnabled = 'bWysiwyg' in this.opt && this.opt.bWysiwyg;
|
Chris@76
|
16 // This doesn't work on Opera as they cannot restore focus after clicking a BBC button.
|
Chris@76
|
17 this.bRichTextPossible = !this.opt.bRichEditOff && ((is_ie5up && !is_ie50) || is_ff || is_opera95up || is_safari || is_chrome) && !(is_iphone || is_android);
|
Chris@76
|
18
|
Chris@76
|
19 this.oFrameHandle = null;
|
Chris@76
|
20 this.oFrameDocument = null;
|
Chris@76
|
21 this.oFrameWindow = null;
|
Chris@76
|
22
|
Chris@76
|
23 // These hold the breadcrumb.
|
Chris@76
|
24 this.oBreadHandle = null;
|
Chris@76
|
25 this.oResizerElement = null;
|
Chris@76
|
26
|
Chris@76
|
27 // Kinda holds all the useful stuff.
|
Chris@76
|
28 this.aKeyboardShortcuts = new Array();
|
Chris@76
|
29
|
Chris@76
|
30 // This tracks the cursor position on IE to avoid refocus problems.
|
Chris@76
|
31 this.cursorX = 0;
|
Chris@76
|
32 this.cursorY = 0;
|
Chris@76
|
33
|
Chris@76
|
34 // This is all the elements that can have a simple execCommand.
|
Chris@76
|
35 this.oSimpleExec = {
|
Chris@76
|
36 b: 'bold',
|
Chris@76
|
37 u: 'underline',
|
Chris@76
|
38 i: 'italic',
|
Chris@76
|
39 s: 'strikethrough',
|
Chris@76
|
40 left: 'justifyleft',
|
Chris@76
|
41 center: 'justifycenter',
|
Chris@76
|
42 right: 'justifyright',
|
Chris@76
|
43 hr: 'inserthorizontalrule',
|
Chris@76
|
44 list: 'insertunorderedlist',
|
Chris@76
|
45 orderlist: 'insertorderedlist',
|
Chris@76
|
46 sub: 'subscript',
|
Chris@76
|
47 sup: 'superscript',
|
Chris@76
|
48 indent: 'indent',
|
Chris@76
|
49 outdent: 'outdent'
|
Chris@76
|
50 }
|
Chris@76
|
51
|
Chris@76
|
52 // Codes to call a private function
|
Chris@76
|
53 this.oSmfExec = {
|
Chris@76
|
54 unformat: 'removeFormatting',
|
Chris@76
|
55 toggle: 'toggleView'
|
Chris@76
|
56 }
|
Chris@76
|
57
|
Chris@76
|
58 // Any special breadcrumb mappings to ensure we show a consistant tag name.
|
Chris@76
|
59 this.breadCrumbNameTags = {
|
Chris@76
|
60 strike: 's',
|
Chris@76
|
61 strong: 'b',
|
Chris@76
|
62 em: 'i'
|
Chris@76
|
63 }
|
Chris@76
|
64
|
Chris@76
|
65 this.aBreadCrumbNameStyles = [
|
Chris@76
|
66 {
|
Chris@76
|
67 sStyleType: 'text-decoration',
|
Chris@76
|
68 sStyleValue: 'underline',
|
Chris@76
|
69 sBbcTag: 'u'
|
Chris@76
|
70 },
|
Chris@76
|
71 {
|
Chris@76
|
72 sStyleType: 'text-decoration',
|
Chris@76
|
73 sStyleValue: 'line-through',
|
Chris@76
|
74 sBbcTag: 's'
|
Chris@76
|
75 },
|
Chris@76
|
76 {
|
Chris@76
|
77 sStyleType: 'text-align',
|
Chris@76
|
78 sStyleValue: 'left',
|
Chris@76
|
79 sBbcTag: 'left'
|
Chris@76
|
80 },
|
Chris@76
|
81 {
|
Chris@76
|
82 sStyleType: 'text-align',
|
Chris@76
|
83 sStyleValue: 'center',
|
Chris@76
|
84 sBbcTag: 'center'
|
Chris@76
|
85 },
|
Chris@76
|
86 {
|
Chris@76
|
87 sStyleType: 'text-align',
|
Chris@76
|
88 sStyleValue: 'right',
|
Chris@76
|
89 sBbcTag: 'right'
|
Chris@76
|
90 },
|
Chris@76
|
91 {
|
Chris@76
|
92 sStyleType: 'font-weight',
|
Chris@76
|
93 sStyleValue: 'bold',
|
Chris@76
|
94 sBbcTag: 'b'
|
Chris@76
|
95 },
|
Chris@76
|
96 {
|
Chris@76
|
97 sStyleType: 'font-style',
|
Chris@76
|
98 sStyleValue: 'italic',
|
Chris@76
|
99 sBbcTag: 'i'
|
Chris@76
|
100 }
|
Chris@76
|
101 ];
|
Chris@76
|
102
|
Chris@76
|
103 // All the fonts in the world.
|
Chris@76
|
104 this.aFontFaces = [
|
Chris@76
|
105 'Arial',
|
Chris@76
|
106 'Arial Black',
|
Chris@76
|
107 'Impact',
|
Chris@76
|
108 'Verdana',
|
Chris@76
|
109 'Times New Roman',
|
Chris@76
|
110 'Georgia',
|
Chris@76
|
111 'Andale Mono',
|
Chris@76
|
112 'Trebuchet MS',
|
Chris@76
|
113 'Comic Sans MS'
|
Chris@76
|
114 ];
|
Chris@76
|
115 // Font maps (HTML => CSS size)
|
Chris@76
|
116 this.aFontSizes = [
|
Chris@76
|
117 0,
|
Chris@76
|
118 8,
|
Chris@76
|
119 10,
|
Chris@76
|
120 12,
|
Chris@76
|
121 14,
|
Chris@76
|
122 18,
|
Chris@76
|
123 24,
|
Chris@76
|
124 36
|
Chris@76
|
125 ];
|
Chris@76
|
126 // Color maps! (hex => name)
|
Chris@76
|
127 this.oFontColors = {
|
Chris@76
|
128 black: '#000000',
|
Chris@76
|
129 red: '#ff0000',
|
Chris@76
|
130 yellow: '#ffff00',
|
Chris@76
|
131 pink: '#ffc0cb',
|
Chris@76
|
132 green: '#008000',
|
Chris@76
|
133 orange: '#ffa500',
|
Chris@76
|
134 purple: '#800080',
|
Chris@76
|
135 blue: '#0000ff',
|
Chris@76
|
136 beige: '#f5f5dc',
|
Chris@76
|
137 brown: '#a52a2a',
|
Chris@76
|
138 teal: '#008080',
|
Chris@76
|
139 navy: '#000080',
|
Chris@76
|
140 maroon: '#800000',
|
Chris@76
|
141 limegreen: '#32cd32'
|
Chris@76
|
142 }
|
Chris@76
|
143
|
Chris@76
|
144 this.sFormId = 'sFormId' in this.opt ? this.opt.sFormId : 'postmodify';
|
Chris@76
|
145 this.iArrayPosition = smf_editorArray.length;
|
Chris@76
|
146
|
Chris@76
|
147 // Current resize state.
|
Chris@76
|
148 this.osmc_EditorCurrentResize = {};
|
Chris@76
|
149
|
Chris@76
|
150 this.init();
|
Chris@76
|
151 }
|
Chris@76
|
152
|
Chris@76
|
153 smc_Editor.prototype.init = function()
|
Chris@76
|
154 {
|
Chris@76
|
155 // Define the event wrapper functions.
|
Chris@76
|
156 var oCaller = this;
|
Chris@76
|
157 this.aEventWrappers = {
|
Chris@76
|
158 editorKeyUp: function(oEvent) {return oCaller.editorKeyUp(oEvent);},
|
Chris@76
|
159 shortcutCheck: function(oEvent) {return oCaller.shortcutCheck(oEvent);},
|
Chris@76
|
160 editorBlur: function(oEvent) {return oCaller.editorBlur(oEvent);},
|
Chris@76
|
161 editorFocus: function(oEvent) {return oCaller.editorFocus(oEvent);},
|
Chris@76
|
162 startResize: function(oEvent) {return oCaller.startResize(oEvent);},
|
Chris@76
|
163 resizeOverDocument: function(oEvent) {return oCaller.resizeOverDocument(oEvent);},
|
Chris@76
|
164 endResize: function(oEvent) {return oCaller.endResize(oEvent);},
|
Chris@76
|
165 resizeOverIframe: function(oEvent) {return oCaller.resizeOverIframe(oEvent);}
|
Chris@76
|
166 };
|
Chris@76
|
167
|
Chris@76
|
168 // Set the textHandle.
|
Chris@76
|
169 this.oTextHandle = document.getElementById(this.opt.sUniqueId);
|
Chris@76
|
170
|
Chris@76
|
171 // Ensure the currentText is set correctly depending on the mode.
|
Chris@76
|
172 if (this.sCurrentText == '' && !this.bRichTextEnabled)
|
Chris@76
|
173 this.sCurrentText = getInnerHTML(this.oTextHandle).php_unhtmlspecialchars();
|
Chris@76
|
174
|
Chris@76
|
175 // Only try to do this if rich text is supported.
|
Chris@76
|
176 if (this.bRichTextPossible)
|
Chris@76
|
177 {
|
Chris@76
|
178 // Make the iframe itself, stick it next to the current text area, and give it an ID.
|
Chris@76
|
179 this.oFrameHandle = document.createElement('iframe');
|
Chris@76
|
180 this.oFrameHandle.src = 'about:blank';
|
Chris@76
|
181 this.oFrameHandle.id = 'html_' + this.opt.sUniqueId;
|
Chris@76
|
182 this.oFrameHandle.className = 'rich_editor_frame';
|
Chris@76
|
183 this.oFrameHandle.style.display = 'none';
|
Chris@76
|
184 this.oFrameHandle.style.margin = '0px';
|
Chris@76
|
185 this.oFrameHandle.tabIndex = this.oTextHandle.tabIndex;
|
Chris@76
|
186 this.oTextHandle.parentNode.appendChild(this.oFrameHandle);
|
Chris@76
|
187
|
Chris@76
|
188 // Create some handy shortcuts.
|
Chris@76
|
189 this.oFrameDocument = this.oFrameHandle.contentDocument ? this.oFrameHandle.contentDocument : ('contentWindow' in this.oFrameHandle ? this.oFrameHandle.contentWindow.document : this.oFrameHandle.document);
|
Chris@76
|
190 this.oFrameWindow = 'contentWindow' in this.oFrameHandle ? this.oFrameHandle.contentWindow : this.oFrameHandle.document.parentWindow;
|
Chris@76
|
191
|
Chris@76
|
192 // Create the debug window... and stick this under the main frame - make it invisible by default.
|
Chris@76
|
193 this.oBreadHandle = document.createElement('div');
|
Chris@76
|
194 this.oBreadHandle.id = 'bread_' . uid;
|
Chris@76
|
195 this.oBreadHandle.style.visibility = 'visible';
|
Chris@76
|
196 this.oBreadHandle.style.display = 'none';
|
Chris@76
|
197 this.oFrameHandle.parentNode.appendChild(this.oBreadHandle);
|
Chris@76
|
198
|
Chris@76
|
199 // Size the iframe dimensions to something sensible.
|
Chris@76
|
200 this.oFrameHandle.style.width = this.sEditWidth;
|
Chris@76
|
201 this.oFrameHandle.style.height = this.sEditHeight;
|
Chris@76
|
202 this.oFrameHandle.style.visibility = 'visible';
|
Chris@76
|
203
|
Chris@76
|
204 // Only bother formatting the debug window if debug is enabled.
|
Chris@76
|
205 if (this.showDebug)
|
Chris@76
|
206 {
|
Chris@76
|
207 this.oBreadHandle.style.width = this.sEditWidth;
|
Chris@76
|
208 this.oBreadHandle.style.height = '20px';
|
Chris@76
|
209 this.oBreadHandle.className = 'windowbg2';
|
Chris@76
|
210 this.oBreadHandle.style.border = '1px black solid';
|
Chris@76
|
211 this.oBreadHandle.style.display = '';
|
Chris@76
|
212 }
|
Chris@76
|
213
|
Chris@76
|
214 // Populate the editor with nothing by default.
|
Chris@76
|
215 if (!is_opera95up)
|
Chris@76
|
216 {
|
Chris@76
|
217 this.oFrameDocument.open();
|
Chris@76
|
218 this.oFrameDocument.write('');
|
Chris@76
|
219 this.oFrameDocument.close();
|
Chris@76
|
220 }
|
Chris@76
|
221
|
Chris@76
|
222 // Right to left mode?
|
Chris@76
|
223 if (this.opt.bRTL)
|
Chris@76
|
224 {
|
Chris@76
|
225 this.oFrameDocument.dir = "rtl";
|
Chris@76
|
226 this.oFrameDocument.body.dir = "rtl";
|
Chris@76
|
227 }
|
Chris@76
|
228
|
Chris@76
|
229 // Mark it as editable...
|
Chris@76
|
230 if (this.oFrameDocument.body.contentEditable)
|
Chris@76
|
231 this.oFrameDocument.body.contentEditable = true;
|
Chris@76
|
232 else
|
Chris@76
|
233 {
|
Chris@76
|
234 this.oFrameHandle.style.display = '';
|
Chris@76
|
235 this.oFrameDocument.designMode = 'on';
|
Chris@76
|
236 this.oFrameHandle.style.display = 'none';
|
Chris@76
|
237 }
|
Chris@76
|
238
|
Chris@76
|
239 // Now we need to try and style the editor - internet explorer allows us to do the whole lot.
|
Chris@76
|
240 if (document.styleSheets['editor_css'] || document.styleSheets['editor_ie_css'])
|
Chris@76
|
241 {
|
Chris@76
|
242 var oMyStyle = this.oFrameDocument.createElement('style');
|
Chris@76
|
243 this.oFrameDocument.documentElement.firstChild.appendChild(oMyStyle);
|
Chris@76
|
244 oMyStyle.styleSheet.cssText = document.styleSheets['editor_ie_css'] ? document.styleSheets['editor_ie_css'].cssText : document.styleSheets['editor_css'].cssText;
|
Chris@76
|
245 }
|
Chris@76
|
246 // Otherwise we seem to have to try to rip out each of the styles one by one!
|
Chris@76
|
247 else if (document.styleSheets.length)
|
Chris@76
|
248 {
|
Chris@76
|
249 var bFoundSomething = false;
|
Chris@76
|
250 // First we need to find the right style sheet.
|
Chris@76
|
251 for (var i = 0, iNumStyleSheets = document.styleSheets.length; i < iNumStyleSheets; i++)
|
Chris@76
|
252 {
|
Chris@76
|
253 // Start off looking for the right style sheet.
|
Chris@76
|
254 if (!document.styleSheets[i].href || document.styleSheets[i].href.indexOf('editor') < 1)
|
Chris@76
|
255 continue;
|
Chris@76
|
256
|
Chris@76
|
257 // Firefox won't allow us to get a CSS file which ain't in the right URL.
|
Chris@76
|
258 try
|
Chris@76
|
259 {
|
Chris@76
|
260 if (document.styleSheets[i].cssRules.length < 1)
|
Chris@76
|
261 continue;
|
Chris@76
|
262 }
|
Chris@76
|
263 catch (e)
|
Chris@76
|
264 {
|
Chris@76
|
265 continue;
|
Chris@76
|
266 }
|
Chris@76
|
267
|
Chris@76
|
268 // Manually try to find the rich_editor class.
|
Chris@76
|
269 for (var r = 0, iNumRules = document.styleSheets[i].cssRules.length; r < iNumRules; r++)
|
Chris@76
|
270 {
|
Chris@76
|
271 // Got the main editor?
|
Chris@76
|
272 if (document.styleSheets[i].cssRules[r].selectorText == '.rich_editor')
|
Chris@76
|
273 {
|
Chris@76
|
274 // Set some possible styles.
|
Chris@76
|
275 if (document.styleSheets[i].cssRules[r].style.color)
|
Chris@76
|
276 this.oFrameDocument.body.style.color = document.styleSheets[i].cssRules[r].style.color;
|
Chris@76
|
277 if (document.styleSheets[i].cssRules[r].style.backgroundColor)
|
Chris@76
|
278 this.oFrameDocument.body.style.backgroundColor = document.styleSheets[i].cssRules[r].style.backgroundColor;
|
Chris@76
|
279 if (document.styleSheets[i].cssRules[r].style.fontSize)
|
Chris@76
|
280 this.oFrameDocument.body.style.fontSize = document.styleSheets[i].cssRules[r].style.fontSize;
|
Chris@76
|
281 if (document.styleSheets[i].cssRules[r].style.fontFamily)
|
Chris@76
|
282 this.oFrameDocument.body.style.fontFamily = document.styleSheets[i].cssRules[r].style.fontFamily;
|
Chris@76
|
283 if (document.styleSheets[i].cssRules[r].style.border)
|
Chris@76
|
284 this.oFrameDocument.body.style.border = document.styleSheets[i].cssRules[r].style.border;
|
Chris@76
|
285 bFoundSomething = true;
|
Chris@76
|
286 }
|
Chris@76
|
287 // The frame?
|
Chris@76
|
288 else if (document.styleSheets[i].cssRules[r].selectorText == '.rich_editor_frame')
|
Chris@76
|
289 {
|
Chris@76
|
290 if (document.styleSheets[i].cssRules[r].style.border)
|
Chris@76
|
291 this.oFrameHandle.style.border = document.styleSheets[i].cssRules[r].style.border;
|
Chris@76
|
292 }
|
Chris@76
|
293 }
|
Chris@76
|
294 }
|
Chris@76
|
295
|
Chris@76
|
296 // Didn't find it?
|
Chris@76
|
297 if (!bFoundSomething)
|
Chris@76
|
298 {
|
Chris@76
|
299 // Do something that is better than nothing.
|
Chris@76
|
300 this.oFrameDocument.body.style.color = 'black';
|
Chris@76
|
301 this.oFrameDocument.body.style.backgroundColor = 'white';
|
Chris@76
|
302 this.oFrameDocument.body.style.fontSize = '78%';
|
Chris@76
|
303 this.oFrameDocument.body.style.fontFamily = '"Verdana", "Arial", "Helvetica", "sans-serif"';
|
Chris@76
|
304 this.oFrameDocument.body.style.border = 'none';
|
Chris@76
|
305 this.oFrameHandle.style.border = '1px solid #808080';
|
Chris@76
|
306 if (is_opera)
|
Chris@76
|
307 this.oFrameDocument.body.style.height = '99%';
|
Chris@76
|
308 }
|
Chris@76
|
309 }
|
Chris@76
|
310
|
Chris@76
|
311 // Apply the class...
|
Chris@76
|
312 this.oFrameDocument.body.className = 'rich_editor';
|
Chris@76
|
313
|
Chris@76
|
314 // Set the frame padding/margin inside the editor.
|
Chris@76
|
315 this.oFrameDocument.body.style.padding = '1px';
|
Chris@76
|
316 this.oFrameDocument.body.style.margin = '0';
|
Chris@76
|
317
|
Chris@76
|
318 // Listen for input.
|
Chris@76
|
319 this.oFrameDocument.instanceRef = this;
|
Chris@76
|
320 this.oFrameHandle.instanceRef = this;
|
Chris@76
|
321 this.oTextHandle.instanceRef = this;
|
Chris@76
|
322
|
Chris@76
|
323 // Attach addEventListener for those browsers that don't support it.
|
Chris@76
|
324 createEventListener(this.oFrameHandle);
|
Chris@76
|
325 createEventListener(this.oFrameDocument);
|
Chris@76
|
326 createEventListener(this.oTextHandle);
|
Chris@76
|
327 createEventListener(window);
|
Chris@76
|
328 createEventListener(document);
|
Chris@76
|
329
|
Chris@76
|
330 // Attach functions to the key and mouse events.
|
Chris@76
|
331 this.oFrameDocument.addEventListener('keyup', this.aEventWrappers.editorKeyUp, true);
|
Chris@76
|
332 this.oFrameDocument.addEventListener('mouseup', this.aEventWrappers.editorKeyUp, true);
|
Chris@76
|
333 this.oFrameDocument.addEventListener('keydown', this.aEventWrappers.shortcutCheck, true);
|
Chris@76
|
334 this.oTextHandle.addEventListener('keydown', this.aEventWrappers.shortcutCheck, true);
|
Chris@76
|
335
|
Chris@76
|
336 if (is_ie)
|
Chris@76
|
337 {
|
Chris@76
|
338 this.oFrameDocument.addEventListener('blur', this.aEventWrappers.editorBlur, true);
|
Chris@76
|
339 this.oFrameDocument.addEventListener('focus', this.aEventWrappers.editorFocus, true);
|
Chris@76
|
340 }
|
Chris@76
|
341
|
Chris@76
|
342 // Show the iframe only if wysiwyrg is on - and hide the text area.
|
Chris@76
|
343 this.oTextHandle.style.display = this.bRichTextEnabled ? 'none' : '';
|
Chris@76
|
344 this.oFrameHandle.style.display = this.bRichTextEnabled ? '' : 'none';
|
Chris@76
|
345 this.oBreadHandle.style.display = this.bRichTextEnabled ? '' : 'none';
|
Chris@76
|
346 }
|
Chris@76
|
347 // If we can't do advanced stuff then just do the basics.
|
Chris@76
|
348 else
|
Chris@76
|
349 {
|
Chris@76
|
350 // Cannot have WYSIWYG anyway!
|
Chris@76
|
351 this.bRichTextEnabled = false;
|
Chris@76
|
352
|
Chris@76
|
353 // We need some of the event handlers.
|
Chris@76
|
354 createEventListener(this.oTextHandle);
|
Chris@76
|
355 createEventListener(window);
|
Chris@76
|
356 createEventListener(document);
|
Chris@76
|
357 }
|
Chris@76
|
358
|
Chris@76
|
359 // Make sure we set the message mode correctly.
|
Chris@76
|
360 document.getElementById(this.opt.sUniqueId + '_mode').value = this.bRichTextEnabled ? 1 : 0;
|
Chris@76
|
361
|
Chris@76
|
362 // Show the resizer.
|
Chris@76
|
363 if (document.getElementById(this.opt.sUniqueId + '_resizer') && (!is_opera || is_opera95up) && !(is_chrome && !this.bRichTextEnabled))
|
Chris@76
|
364 {
|
Chris@76
|
365 // Currently nothing is being resized...I assume!
|
Chris@76
|
366 window.smf_oCurrentResizeEditor = null;
|
Chris@76
|
367
|
Chris@76
|
368 this.oResizerElement = document.getElementById(this.opt.sUniqueId + '_resizer');
|
Chris@76
|
369 this.oResizerElement.style.display = '';
|
Chris@76
|
370
|
Chris@76
|
371 createEventListener(this.oResizerElement);
|
Chris@76
|
372 this.oResizerElement.addEventListener('mousedown', this.aEventWrappers.startResize, false);
|
Chris@76
|
373 }
|
Chris@76
|
374
|
Chris@76
|
375 // Set the text - if WYSIWYG is enabled that is.
|
Chris@76
|
376 if (this.bRichTextEnabled)
|
Chris@76
|
377 {
|
Chris@76
|
378 this.insertText(this.sCurrentText, true);
|
Chris@76
|
379
|
Chris@76
|
380 // Better make us the focus!
|
Chris@76
|
381 this.setFocus();
|
Chris@76
|
382 }
|
Chris@76
|
383
|
Chris@76
|
384 // Finally, register shortcuts.
|
Chris@76
|
385 this.registerDefaultShortcuts();
|
Chris@76
|
386 this.updateEditorControls();
|
Chris@76
|
387 }
|
Chris@76
|
388
|
Chris@76
|
389 // Return the current text.
|
Chris@76
|
390 smc_Editor.prototype.getText = function(bPrepareEntities, bModeOverride)
|
Chris@76
|
391 {
|
Chris@76
|
392 var bCurMode = typeof(bModeOverride) != 'undefined' ? bModeOverride : this.bRichTextEnabled;
|
Chris@76
|
393
|
Chris@76
|
394 if (!bCurMode || this.oFrameDocument == null)
|
Chris@76
|
395 {
|
Chris@76
|
396 var sText = this.oTextHandle.value;
|
Chris@76
|
397 if (bPrepareEntities)
|
Chris@76
|
398 sText = sText.replace(/</g, '#smlt#').replace(/>/g, '#smgt#').replace(/&/g, '#smamp#');
|
Chris@76
|
399 }
|
Chris@76
|
400 else
|
Chris@76
|
401 {
|
Chris@76
|
402 var sText = this.oFrameDocument.body.innerHTML;
|
Chris@76
|
403 if (bPrepareEntities)
|
Chris@76
|
404 sText = sText.replace(/</g, '#smlt#').replace(/>/g, '#smgt#').replace(/&/g, '#smamp#');
|
Chris@76
|
405 }
|
Chris@76
|
406
|
Chris@76
|
407 // Clean it up - including removing semi-colons.
|
Chris@76
|
408 if (bPrepareEntities)
|
Chris@76
|
409 sText = sText.replace(/ /g, ' ').replace(/;/g, '#smcol#');
|
Chris@76
|
410
|
Chris@76
|
411 // Return it.
|
Chris@76
|
412 return sText;
|
Chris@76
|
413 }
|
Chris@76
|
414
|
Chris@76
|
415 // Return the current text.
|
Chris@76
|
416 smc_Editor.prototype.unprotectText = function(sText)
|
Chris@76
|
417 {
|
Chris@76
|
418 var bCurMode = typeof(bModeOverride) != 'undefined' ? bModeOverride : this.bRichTextEnabled;
|
Chris@76
|
419
|
Chris@76
|
420 // This restores smlt, smgt and smamp into boring entities, to unprotect against XML'd information like quotes.
|
Chris@76
|
421 sText = sText.replace(/#smlt#/g, '<').replace(/#smgt#/g, '>').replace(/#smamp#/g, '&');
|
Chris@76
|
422
|
Chris@76
|
423 // Return it.
|
Chris@76
|
424 return sText;
|
Chris@76
|
425 }
|
Chris@76
|
426
|
Chris@76
|
427 smc_Editor.prototype.editorKeyUp = function()
|
Chris@76
|
428 {
|
Chris@76
|
429 // Rebuild the breadcrumb.
|
Chris@76
|
430 this.updateEditorControls();
|
Chris@76
|
431 }
|
Chris@76
|
432
|
Chris@76
|
433 smc_Editor.prototype.editorBlur = function()
|
Chris@76
|
434 {
|
Chris@76
|
435 if (!is_ie)
|
Chris@76
|
436 return;
|
Chris@76
|
437
|
Chris@76
|
438 // Need to do something here.
|
Chris@76
|
439 }
|
Chris@76
|
440
|
Chris@76
|
441 smc_Editor.prototype.editorFocus = function()
|
Chris@76
|
442 {
|
Chris@76
|
443 if (!is_ie)
|
Chris@76
|
444 return;
|
Chris@76
|
445
|
Chris@76
|
446 // Need to do something here.
|
Chris@76
|
447 }
|
Chris@76
|
448
|
Chris@76
|
449 // Rebuild the breadcrumb etc - and set things to the correct context.
|
Chris@76
|
450 smc_Editor.prototype.updateEditorControls = function()
|
Chris@76
|
451 {
|
Chris@76
|
452 // Everything else is specific to HTML mode.
|
Chris@76
|
453 if (!this.bRichTextEnabled)
|
Chris@76
|
454 {
|
Chris@76
|
455 // Set none of the buttons active.
|
Chris@76
|
456 if (this.opt.oBBCBox)
|
Chris@76
|
457 this.opt.oBBCBox.setActive([]);
|
Chris@76
|
458 return;
|
Chris@76
|
459 }
|
Chris@76
|
460
|
Chris@76
|
461 var aCrumb = new Array();
|
Chris@76
|
462 var aAllCrumbs = new Array();
|
Chris@76
|
463 var iMaxLength = 6;
|
Chris@76
|
464
|
Chris@76
|
465 // What is the current element?
|
Chris@76
|
466 var oCurTag = this.getCurElement();
|
Chris@76
|
467
|
Chris@76
|
468 var i = 0;
|
Chris@76
|
469 while (typeof(oCurTag) == 'object' && oCurTag != null && oCurTag.nodeName.toLowerCase() != 'body' && i < iMaxLength)
|
Chris@76
|
470 {
|
Chris@76
|
471 aCrumb[i++] = oCurTag;
|
Chris@76
|
472 oCurTag = oCurTag.parentNode;
|
Chris@76
|
473 }
|
Chris@76
|
474
|
Chris@76
|
475 // Now print out the tree.
|
Chris@76
|
476 var sTree = '';
|
Chris@76
|
477 var sCurFontName = '';
|
Chris@76
|
478 var sCurFontSize = '';
|
Chris@76
|
479 var sCurFontColor = '';
|
Chris@76
|
480 for (var i = 0, iNumCrumbs = aCrumb.length; i < iNumCrumbs; i++)
|
Chris@76
|
481 {
|
Chris@76
|
482 var sCrumbName = aCrumb[i].nodeName.toLowerCase();
|
Chris@76
|
483
|
Chris@76
|
484 // Does it have an alternative name?
|
Chris@76
|
485 if (sCrumbName in this.breadCrumbNameTags)
|
Chris@76
|
486 sCrumbName = this.breadCrumbNameTags[sCrumbName];
|
Chris@76
|
487 // Don't bother with this...
|
Chris@76
|
488 else if (sCrumbName == 'p')
|
Chris@76
|
489 continue;
|
Chris@76
|
490 // A link?
|
Chris@76
|
491 else if (sCrumbName == 'a')
|
Chris@76
|
492 {
|
Chris@76
|
493 var sUrlInfo = aCrumb[i].getAttribute('href');
|
Chris@76
|
494 sCrumbName = 'url';
|
Chris@76
|
495 if (typeof(sUrlInfo) == 'string')
|
Chris@76
|
496 {
|
Chris@76
|
497 if (sUrlInfo.substr(0, 3) == 'ftp')
|
Chris@76
|
498 sCrumbName = 'ftp';
|
Chris@76
|
499 else if (sUrlInfo.substr(0, 6) == 'mailto')
|
Chris@76
|
500 sCrumbName = 'email';
|
Chris@76
|
501 }
|
Chris@76
|
502 }
|
Chris@76
|
503 else if (sCrumbName == 'span' || sCrumbName == 'div')
|
Chris@76
|
504 {
|
Chris@76
|
505 if (aCrumb[i].style)
|
Chris@76
|
506 {
|
Chris@76
|
507 for (var j = 0, iNumStyles = this.aBreadCrumbNameStyles.length; j < iNumStyles; j++)
|
Chris@76
|
508 {
|
Chris@76
|
509 // Do we have a font?
|
Chris@76
|
510 if (aCrumb[i].style.fontFamily && aCrumb[i].style.fontFamily != '' && sCurFontName == '')
|
Chris@76
|
511 {
|
Chris@76
|
512 sCurFontName = aCrumb[i].style.fontFamily;
|
Chris@76
|
513 sCrumbName = 'face';
|
Chris@76
|
514 }
|
Chris@76
|
515 // ... or a font size?
|
Chris@76
|
516 if (aCrumb[i].style.fontSize && aCrumb[i].style.fontSize != '' && sCurFontSize == '')
|
Chris@76
|
517 {
|
Chris@76
|
518 sCurFontSize = aCrumb[i].style.fontSize;
|
Chris@76
|
519 sCrumbName = 'size';
|
Chris@76
|
520 }
|
Chris@76
|
521 // ... even color?
|
Chris@76
|
522 if (aCrumb[i].style.color && aCrumb[i].style.color != '' && sCurFontColor == '')
|
Chris@76
|
523 {
|
Chris@76
|
524 sCurFontColor = aCrumb[i].style.color;
|
Chris@76
|
525 if (in_array(sCurFontColor, this.oFontColors))
|
Chris@76
|
526 sCurFontColor = array_search(sCurFontColor, this.oFontColors);
|
Chris@76
|
527 sCrumbName = 'color';
|
Chris@76
|
528 }
|
Chris@76
|
529
|
Chris@76
|
530 if (this.aBreadCrumbNameStyles[j].sStyleType == 'text-align' && aCrumb[i].style.textAlign && aCrumb[i].style.textAlign == this.aBreadCrumbNameStyles[j].sStyleValue)
|
Chris@76
|
531 sCrumbName = this.aBreadCrumbNameStyles[j].sBbcTag;
|
Chris@76
|
532 else if (this.aBreadCrumbNameStyles[j].sStyleType == 'text-decoration' && aCrumb[i].style.textDecoration && aCrumb[i].style.textDecoration == this.aBreadCrumbNameStyles[j].sStyleValue)
|
Chris@76
|
533 sCrumbName = this.aBreadCrumbNameStyles[j].sBbcTag;
|
Chris@76
|
534 else if (this.aBreadCrumbNameStyles[j].sStyleType == 'font-weight' && aCrumb[i].style.fontWeight && aCrumb[i].style.fontWeight == this.aBreadCrumbNameStyles[j].sStyleValue)
|
Chris@76
|
535 sCrumbName = this.aBreadCrumbNameStyles[j].sBbcTag;
|
Chris@76
|
536 else if (this.aBreadCrumbNameStyles[j].sStyleType == 'font-style' && aCrumb[i].style.fontStyle && aCrumb[i].style.fontStyle == this.aBreadCrumbNameStyles[j].sStyleValue)
|
Chris@76
|
537 sCrumbName = this.aBreadCrumbNameStyles[j].sBbcTag;
|
Chris@76
|
538 }
|
Chris@76
|
539 }
|
Chris@76
|
540 }
|
Chris@76
|
541 // Do we have a font?
|
Chris@76
|
542 else if (sCrumbName == 'font')
|
Chris@76
|
543 {
|
Chris@76
|
544 if (aCrumb[i].getAttribute('face') && sCurFontName == '')
|
Chris@76
|
545 {
|
Chris@76
|
546 sCurFontName = aCrumb[i].getAttribute('face').toLowerCase();
|
Chris@76
|
547 sCrumbName = 'face';
|
Chris@76
|
548 }
|
Chris@76
|
549 if (aCrumb[i].getAttribute('size') && sCurFontSize == '')
|
Chris@76
|
550 {
|
Chris@76
|
551 sCurFontSize = aCrumb[i].getAttribute('size');
|
Chris@76
|
552 sCrumbName = 'size';
|
Chris@76
|
553 }
|
Chris@76
|
554 if (aCrumb[i].getAttribute('color') && sCurFontColor == '')
|
Chris@76
|
555 {
|
Chris@76
|
556 sCurFontColor = aCrumb[i].getAttribute('color');
|
Chris@76
|
557 if (in_array(sCurFontColor, this.oFontColors))
|
Chris@76
|
558 sCurFontColor = array_search(sCurFontColor, this.oFontColors);
|
Chris@76
|
559 sCrumbName = 'color';
|
Chris@76
|
560 }
|
Chris@76
|
561 // Something else - ignore.
|
Chris@76
|
562 if (sCrumbName == 'font')
|
Chris@76
|
563 continue;
|
Chris@76
|
564 }
|
Chris@76
|
565
|
Chris@76
|
566 sTree += (i != 0 ? ' <strong>></strong>' : '') + ' ' + sCrumbName;
|
Chris@76
|
567 aAllCrumbs[aAllCrumbs.length] = sCrumbName;
|
Chris@76
|
568 }
|
Chris@76
|
569
|
Chris@76
|
570 // Since we're in WYSIWYG state, show the toggle button as active.
|
Chris@76
|
571 aAllCrumbs[aAllCrumbs.length] = 'toggle';
|
Chris@76
|
572
|
Chris@76
|
573 this.opt.oBBCBox.setActive(aAllCrumbs);
|
Chris@76
|
574
|
Chris@76
|
575 // Try set the font boxes correct.
|
Chris@76
|
576 this.opt.oBBCBox.setSelect('sel_face', sCurFontName);
|
Chris@76
|
577 this.opt.oBBCBox.setSelect('sel_size', sCurFontSize);
|
Chris@76
|
578 this.opt.oBBCBox.setSelect('sel_color', sCurFontColor);
|
Chris@76
|
579
|
Chris@76
|
580 if (this.showDebug)
|
Chris@76
|
581 setInnerHTML(this.oBreadHandle, sTree);
|
Chris@76
|
582 }
|
Chris@76
|
583
|
Chris@76
|
584 // Set the HTML content to be that of the text box - if we are in wysiwyg mode.
|
Chris@76
|
585 smc_Editor.prototype.doSubmit = function()
|
Chris@76
|
586 {
|
Chris@76
|
587 if (this.bRichTextEnabled)
|
Chris@76
|
588 this.oTextHandle.value = this.oFrameDocument.body.innerHTML;
|
Chris@76
|
589 }
|
Chris@76
|
590
|
Chris@76
|
591 // Populate the box with text.
|
Chris@76
|
592 smc_Editor.prototype.insertText = function(sText, bClear, bForceEntityReverse, iMoveCursorBack)
|
Chris@76
|
593 {
|
Chris@76
|
594 if (bForceEntityReverse)
|
Chris@76
|
595 sText = this.unprotectText(sText);
|
Chris@76
|
596
|
Chris@76
|
597 // Erase it all?
|
Chris@76
|
598 if (bClear)
|
Chris@76
|
599 {
|
Chris@76
|
600 if (this.bRichTextEnabled)
|
Chris@76
|
601 {
|
Chris@76
|
602 // This includes a work around for FF to get the cursor to show!
|
Chris@76
|
603 this.oFrameDocument.body.innerHTML = sText;
|
Chris@76
|
604
|
Chris@76
|
605 // If FF trick the cursor into coming back!
|
Chris@76
|
606 if (is_ff || is_opera)
|
Chris@76
|
607 {
|
Chris@76
|
608 // For some entirely unknown reason FF3 Beta 2 and some Opera versions
|
Chris@76
|
609 // require this.
|
Chris@76
|
610 this.oFrameDocument.body.contentEditable = false;
|
Chris@76
|
611
|
Chris@76
|
612 this.oFrameDocument.designMode = 'off';
|
Chris@76
|
613 this.oFrameDocument.designMode = 'on';
|
Chris@76
|
614 }
|
Chris@76
|
615 }
|
Chris@76
|
616 else
|
Chris@76
|
617 this.oTextHandle.value = sText;
|
Chris@76
|
618 }
|
Chris@76
|
619 else
|
Chris@76
|
620 {
|
Chris@76
|
621 this.setFocus();
|
Chris@76
|
622 if (this.bRichTextEnabled)
|
Chris@76
|
623 {
|
Chris@76
|
624 // IE croaks if you have an image selected and try to insert!
|
Chris@76
|
625 if ('selection' in this.oFrameDocument && this.oFrameDocument.selection.type != 'Text' && this.oFrameDocument.selection.type != 'None' && this.oFrameDocument.selection.clear)
|
Chris@76
|
626 this.oFrameDocument.selection.clear();
|
Chris@76
|
627
|
Chris@76
|
628 var oRange = this.getRange();
|
Chris@76
|
629
|
Chris@76
|
630 if (oRange.pasteHTML)
|
Chris@76
|
631 {
|
Chris@76
|
632 oRange.pasteHTML(sText);
|
Chris@76
|
633
|
Chris@76
|
634 // Do we want to move the cursor back at all?
|
Chris@76
|
635 if (iMoveCursorBack)
|
Chris@76
|
636 oRange.moveEnd('character', -iMoveCursorBack);
|
Chris@76
|
637
|
Chris@76
|
638 oRange.select();
|
Chris@76
|
639 }
|
Chris@76
|
640 else
|
Chris@76
|
641 {
|
Chris@76
|
642 // If the cursor needs to be positioned, insert the last fragment first.
|
Chris@76
|
643 if (typeof(iMoveCursorBack) != 'undefined' && iMoveCursorBack > 0 && sText.length > iMoveCursorBack)
|
Chris@76
|
644 {
|
Chris@76
|
645 var oSelection = this.getSelect(false, false);
|
Chris@76
|
646 var oRange = oSelection.getRangeAt(0);
|
Chris@76
|
647 oRange.insertNode(this.oFrameDocument.createTextNode(sText.substr(sText.length - iMoveCursorBack)));
|
Chris@76
|
648 }
|
Chris@76
|
649
|
Chris@76
|
650 this.smf_execCommand('inserthtml', false, typeof(iMoveCursorBack) == 'undefined' ? sText : sText.substr(0, sText.length - iMoveCursorBack));
|
Chris@76
|
651 }
|
Chris@76
|
652 }
|
Chris@76
|
653 else
|
Chris@76
|
654 {
|
Chris@76
|
655 replaceText(sText, this.oTextHandle);
|
Chris@76
|
656 }
|
Chris@76
|
657 }
|
Chris@76
|
658 }
|
Chris@76
|
659
|
Chris@76
|
660
|
Chris@76
|
661 // Special handler for WYSIWYG.
|
Chris@76
|
662 smc_Editor.prototype.smf_execCommand = function(sCommand, bUi, sValue)
|
Chris@76
|
663 {
|
Chris@76
|
664 return this.oFrameDocument.execCommand(sCommand, bUi, sValue);
|
Chris@76
|
665 }
|
Chris@76
|
666
|
Chris@76
|
667 smc_Editor.prototype.insertSmiley = function(oSmileyProperties)
|
Chris@76
|
668 {
|
Chris@76
|
669 // In text mode we just add it in as we always did.
|
Chris@76
|
670 if (!this.bRichTextEnabled)
|
Chris@76
|
671 this.insertText(' ' + oSmileyProperties.sCode);
|
Chris@76
|
672
|
Chris@76
|
673 // Otherwise we need to do a whole image...
|
Chris@76
|
674 else
|
Chris@76
|
675 {
|
Chris@76
|
676 var iUniqueSmileyId = 1000 + Math.floor(Math.random() * 100000);
|
Chris@76
|
677 this.insertText('<img src="' + oSmileyProperties.sSrc + '" id="smiley_' + iUniqueSmileyId + '_' + oSmileyProperties.sSrc.replace(/^.*\//, '') + '" onresizestart="return false;" align="bottom" alt="" title="' + oSmileyProperties.sDescription.php_htmlspecialchars() + '" style="padding: 0 3px 0 3px;" />');
|
Chris@76
|
678 }
|
Chris@76
|
679 }
|
Chris@76
|
680
|
Chris@76
|
681 smc_Editor.prototype.handleButtonClick = function (oButtonProperties)
|
Chris@76
|
682 {
|
Chris@76
|
683 this.setFocus();
|
Chris@76
|
684
|
Chris@76
|
685 // A special SMF function?
|
Chris@76
|
686 if (oButtonProperties.sCode in this.oSmfExec)
|
Chris@76
|
687 this[this.oSmfExec[oButtonProperties.sCode]]();
|
Chris@76
|
688
|
Chris@76
|
689 else
|
Chris@76
|
690 {
|
Chris@76
|
691 // In text this is easy...
|
Chris@76
|
692 if (!this.bRichTextEnabled)
|
Chris@76
|
693 {
|
Chris@76
|
694 // Replace?
|
Chris@76
|
695 if (!('sAfter' in oButtonProperties) || oButtonProperties.sAfter == null)
|
Chris@76
|
696 replaceText(oButtonProperties.sBefore.replace(/\\n/g, '\n'), this.oTextHandle)
|
Chris@76
|
697
|
Chris@76
|
698 // Surround!
|
Chris@76
|
699 else
|
Chris@76
|
700 surroundText(oButtonProperties.sBefore.replace(/\\n/g, '\n'), oButtonProperties.sAfter.replace(/\\n/g, '\n'), this.oTextHandle)
|
Chris@76
|
701 }
|
Chris@76
|
702 else
|
Chris@76
|
703 {
|
Chris@76
|
704 // Is it easy?
|
Chris@76
|
705 if (oButtonProperties.sCode in this.oSimpleExec)
|
Chris@76
|
706 this.smf_execCommand(this.oSimpleExec[oButtonProperties.sCode], false, null);
|
Chris@76
|
707
|
Chris@76
|
708 // A link?
|
Chris@76
|
709 else if (oButtonProperties.sCode == 'url' || oButtonProperties.sCode == 'email' || oButtonProperties.sCode == 'ftp')
|
Chris@76
|
710 this.insertLink(oButtonProperties.sCode);
|
Chris@76
|
711
|
Chris@76
|
712 // Maybe an image?
|
Chris@76
|
713 else if (oButtonProperties.sCode == 'img')
|
Chris@76
|
714 this.insertImage();
|
Chris@76
|
715
|
Chris@76
|
716 // Everything else means doing something ourselves.
|
Chris@76
|
717 else if ('sBefore' in oButtonProperties)
|
Chris@76
|
718 this.insertCustomHTML(oButtonProperties.sBefore.replace(/\\n/g, '\n'), oButtonProperties.sAfter.replace(/\\n/g, '\n'));
|
Chris@76
|
719
|
Chris@76
|
720 }
|
Chris@76
|
721 }
|
Chris@76
|
722
|
Chris@76
|
723 this.updateEditorControls();
|
Chris@76
|
724
|
Chris@76
|
725 // Finally set the focus.
|
Chris@76
|
726 this.setFocus();
|
Chris@76
|
727 }
|
Chris@76
|
728
|
Chris@76
|
729 // Changing a select box?
|
Chris@76
|
730 smc_Editor.prototype.handleSelectChange = function (oSelectProperties)
|
Chris@76
|
731 {
|
Chris@76
|
732 this.setFocus();
|
Chris@76
|
733
|
Chris@76
|
734 var sValue = oSelectProperties.oSelect.value;
|
Chris@76
|
735 if (sValue == '')
|
Chris@76
|
736 return true;
|
Chris@76
|
737
|
Chris@76
|
738 // Changing font face?
|
Chris@76
|
739 if (oSelectProperties.sName == 'sel_face')
|
Chris@76
|
740 {
|
Chris@76
|
741 // Not in HTML mode?
|
Chris@76
|
742 if (!this.bRichTextEnabled)
|
Chris@76
|
743 {
|
Chris@76
|
744 sValue = sValue.replace(/"/, '');
|
Chris@76
|
745 surroundText('[font=' + sValue + ']', '[/font]', this.oTextHandle);
|
Chris@76
|
746 oSelectProperties.oSelect.selectedIndex = 0;
|
Chris@76
|
747 }
|
Chris@76
|
748 else
|
Chris@76
|
749 {
|
Chris@76
|
750 if (is_webkit)
|
Chris@76
|
751 this.smf_execCommand('styleWithCSS', false, true);
|
Chris@76
|
752 this.smf_execCommand('fontname', false, sValue);
|
Chris@76
|
753 }
|
Chris@76
|
754 }
|
Chris@76
|
755
|
Chris@76
|
756 // Font size?
|
Chris@76
|
757 else if (oSelectProperties.sName == 'sel_size')
|
Chris@76
|
758 {
|
Chris@76
|
759 // Are we in boring mode?
|
Chris@76
|
760 if (!this.bRichTextEnabled)
|
Chris@76
|
761 {
|
Chris@76
|
762 surroundText('[size=' + this.aFontSizes[sValue] + 'pt]', '[/size]', this.oTextHandle);
|
Chris@76
|
763 oSelectProperties.oSelect.selectedIndex = 0;
|
Chris@76
|
764 }
|
Chris@76
|
765
|
Chris@76
|
766 else
|
Chris@76
|
767 this.smf_execCommand('fontsize', false, sValue);
|
Chris@76
|
768 }
|
Chris@76
|
769 // Or color even?
|
Chris@76
|
770 else if (oSelectProperties.sName == 'sel_color')
|
Chris@76
|
771 {
|
Chris@76
|
772 // Are we in boring mode?
|
Chris@76
|
773 if (!this.bRichTextEnabled)
|
Chris@76
|
774 {
|
Chris@76
|
775 surroundText('[color=' + sValue + ']', '[/color]', this.oTextHandle);
|
Chris@76
|
776 oSelectProperties.oSelect.selectedIndex = 0;
|
Chris@76
|
777 }
|
Chris@76
|
778
|
Chris@76
|
779 else
|
Chris@76
|
780 this.smf_execCommand('forecolor', false, sValue);
|
Chris@76
|
781 }
|
Chris@76
|
782
|
Chris@76
|
783 this.updateEditorControls();
|
Chris@76
|
784
|
Chris@76
|
785 return true;
|
Chris@76
|
786 }
|
Chris@76
|
787
|
Chris@76
|
788 // Put in some custom HTML.
|
Chris@76
|
789 smc_Editor.prototype.insertCustomHTML = function(sLeftTag, sRightTag)
|
Chris@76
|
790 {
|
Chris@76
|
791 var sSelection = this.getSelect(true, true);
|
Chris@76
|
792 if (sSelection.length == 0)
|
Chris@76
|
793 sSelection = '';
|
Chris@76
|
794
|
Chris@76
|
795 // Are we overwriting?
|
Chris@76
|
796 if (sRightTag == '')
|
Chris@76
|
797 this.insertText(sLeftTag);
|
Chris@76
|
798 // If something was selected, replace and position cursor at the end of it.
|
Chris@76
|
799 else if (sSelection.length > 0)
|
Chris@76
|
800 this.insertText(sLeftTag + sSelection + sRightTag, false, false, 0);
|
Chris@76
|
801 // Wrap the tags around the cursor position.
|
Chris@76
|
802 else
|
Chris@76
|
803 this.insertText(sLeftTag + sRightTag, false, false, sRightTag.length);
|
Chris@76
|
804
|
Chris@76
|
805 }
|
Chris@76
|
806
|
Chris@76
|
807 // Insert a URL link.
|
Chris@76
|
808 smc_Editor.prototype.insertLink = function(sType)
|
Chris@76
|
809 {
|
Chris@76
|
810 if (sType == 'email')
|
Chris@76
|
811 var sPromptText = oEditorStrings['prompt_text_email'];
|
Chris@76
|
812 else if (sType == 'ftp')
|
Chris@76
|
813 var sPromptText = oEditorStrings['prompt_text_ftp'];
|
Chris@76
|
814 else
|
Chris@76
|
815 var sPromptText = oEditorStrings['prompt_text_url'];
|
Chris@76
|
816
|
Chris@76
|
817 // IE has a nice prompt for this - others don't.
|
Chris@76
|
818 if (sType != 'email' && sType != 'ftp' && is_ie)
|
Chris@76
|
819 this.smf_execCommand('createlink', true, 'http://');
|
Chris@76
|
820
|
Chris@76
|
821 else
|
Chris@76
|
822 {
|
Chris@76
|
823 // Ask them where to link to.
|
Chris@76
|
824 var sText = prompt(sPromptText, sType == 'email' ? '' : (sType == 'ftp' ? 'ftp://' : 'http://'));
|
Chris@76
|
825 if (!sText)
|
Chris@76
|
826 return;
|
Chris@76
|
827
|
Chris@76
|
828 if (sType == 'email' && sText.indexOf('mailto:') != 0)
|
Chris@76
|
829 sText = 'mailto:' + sText;
|
Chris@76
|
830
|
Chris@76
|
831 // Check if we have text selected and if not force us to have some.
|
Chris@76
|
832 var oCurText = this.getSelect(true, true);
|
Chris@76
|
833
|
Chris@76
|
834 if (oCurText.toString().length != 0)
|
Chris@76
|
835 {
|
Chris@76
|
836 this.smf_execCommand('unlink');
|
Chris@76
|
837 this.smf_execCommand('createlink', false, sText);
|
Chris@76
|
838 }
|
Chris@76
|
839 else
|
Chris@76
|
840 this.insertText('<a href="' + sText + '">' + sText + '</a>');
|
Chris@76
|
841 }
|
Chris@76
|
842 }
|
Chris@76
|
843
|
Chris@76
|
844 smc_Editor.prototype.insertImage = function(sSrc)
|
Chris@76
|
845 {
|
Chris@76
|
846 if (!sSrc)
|
Chris@76
|
847 {
|
Chris@76
|
848 sSrc = prompt(oEditorStrings['prompt_text_img'], 'http://');
|
Chris@76
|
849 if (!sSrc || sSrc.length < 10)
|
Chris@76
|
850 return;
|
Chris@76
|
851 }
|
Chris@76
|
852 this.smf_execCommand('insertimage', false, sSrc);
|
Chris@76
|
853 }
|
Chris@76
|
854
|
Chris@76
|
855 smc_Editor.prototype.getSelect = function(bWantText, bWantHTMLText)
|
Chris@76
|
856 {
|
Chris@76
|
857 if (is_ie && 'selection' in this.oFrameDocument)
|
Chris@76
|
858 {
|
Chris@76
|
859 // Just want plain text?
|
Chris@76
|
860 if (bWantText && !bWantHTMLText)
|
Chris@76
|
861 return this.oFrameDocument.selection.createRange().text;
|
Chris@76
|
862 // We want the HTML flavoured variety?
|
Chris@76
|
863 else if (bWantHTMLText)
|
Chris@76
|
864 return this.oFrameDocument.selection.createRange().htmlText;
|
Chris@76
|
865
|
Chris@76
|
866 return this.oFrameDocument.selection;
|
Chris@76
|
867 }
|
Chris@76
|
868
|
Chris@76
|
869 // This is mainly Firefox.
|
Chris@76
|
870 if ('getSelection' in this.oFrameWindow)
|
Chris@76
|
871 {
|
Chris@76
|
872 // Plain text?
|
Chris@76
|
873 if (bWantText && !bWantHTMLText)
|
Chris@76
|
874 return this.oFrameWindow.getSelection().toString();
|
Chris@76
|
875
|
Chris@76
|
876 // HTML is harder - currently using: http://www.faqts.com/knowledge_base/view.phtml/aid/32427
|
Chris@76
|
877 else if (bWantHTMLText)
|
Chris@76
|
878 {
|
Chris@76
|
879 var oSelection = this.oFrameWindow.getSelection();
|
Chris@76
|
880 if (oSelection.rangeCount > 0)
|
Chris@76
|
881 {
|
Chris@76
|
882 var oRange = oSelection.getRangeAt(0);
|
Chris@76
|
883 var oClonedSelection = oRange.cloneContents();
|
Chris@76
|
884 var oDiv = this.oFrameDocument.createElement('div');
|
Chris@76
|
885 oDiv.appendChild(oClonedSelection);
|
Chris@76
|
886 return oDiv.innerHTML;
|
Chris@76
|
887 }
|
Chris@76
|
888 else
|
Chris@76
|
889 return '';
|
Chris@76
|
890 }
|
Chris@76
|
891
|
Chris@76
|
892 // Want the whole object then.
|
Chris@76
|
893 return this.oFrameWindow.getSelection();
|
Chris@76
|
894 }
|
Chris@76
|
895
|
Chris@76
|
896 // If we're here it's not good.
|
Chris@76
|
897 return this.oFrameDocument.getSelection();
|
Chris@76
|
898 }
|
Chris@76
|
899
|
Chris@76
|
900 smc_Editor.prototype.getRange = function()
|
Chris@76
|
901 {
|
Chris@76
|
902 // Get the current selection.
|
Chris@76
|
903 var oSelection = this.getSelect();
|
Chris@76
|
904
|
Chris@76
|
905 if (!oSelection)
|
Chris@76
|
906 return null;
|
Chris@76
|
907
|
Chris@76
|
908 if (is_ie && oSelection.createRange)
|
Chris@76
|
909 return oSelection.createRange();
|
Chris@76
|
910
|
Chris@76
|
911 return oSelection.rangeCount == 0 ? null : oSelection.getRangeAt(0);
|
Chris@76
|
912 }
|
Chris@76
|
913
|
Chris@76
|
914 // Get the current element.
|
Chris@76
|
915 smc_Editor.prototype.getCurElement = function()
|
Chris@76
|
916 {
|
Chris@76
|
917 var oRange = this.getRange();
|
Chris@76
|
918
|
Chris@76
|
919 if (!oRange)
|
Chris@76
|
920 return null;
|
Chris@76
|
921
|
Chris@76
|
922 if (is_ie)
|
Chris@76
|
923 {
|
Chris@76
|
924 if (oRange.item)
|
Chris@76
|
925 return oRange.item(0);
|
Chris@76
|
926 else
|
Chris@76
|
927 return oRange.parentElement();
|
Chris@76
|
928 }
|
Chris@76
|
929 else
|
Chris@76
|
930 {
|
Chris@76
|
931 var oElement = oRange.commonAncestorContainer;
|
Chris@76
|
932 return this.getParentElement(oElement);
|
Chris@76
|
933 }
|
Chris@76
|
934 }
|
Chris@76
|
935
|
Chris@76
|
936 smc_Editor.prototype.getParentElement = function(oNode)
|
Chris@76
|
937 {
|
Chris@76
|
938 if (oNode.nodeType == 1)
|
Chris@76
|
939 return oNode;
|
Chris@76
|
940
|
Chris@76
|
941 for (var i = 0; i < 50; i++)
|
Chris@76
|
942 {
|
Chris@76
|
943 if (!oNode.parentNode)
|
Chris@76
|
944 break;
|
Chris@76
|
945
|
Chris@76
|
946 oNode = oNode.parentNode;
|
Chris@76
|
947 if (oNode.nodeType == 1)
|
Chris@76
|
948 return oNode;
|
Chris@76
|
949 }
|
Chris@76
|
950 return null;
|
Chris@76
|
951 }
|
Chris@76
|
952
|
Chris@76
|
953 // Remove formatting for the selected text.
|
Chris@76
|
954 smc_Editor.prototype.removeFormatting = function()
|
Chris@76
|
955 {
|
Chris@76
|
956 // Do both at once.
|
Chris@76
|
957 if (this.bRichTextEnabled)
|
Chris@76
|
958 {
|
Chris@76
|
959 this.smf_execCommand('removeformat');
|
Chris@76
|
960 this.smf_execCommand('unlink');
|
Chris@76
|
961 }
|
Chris@76
|
962 // Otherwise do a crude move indeed.
|
Chris@76
|
963 else
|
Chris@76
|
964 {
|
Chris@76
|
965 // Get the current selection first.
|
Chris@76
|
966 if (this.oTextHandle.caretPos)
|
Chris@76
|
967 var sCurrentText = this.oTextHandle.caretPos.text;
|
Chris@76
|
968
|
Chris@76
|
969 else if ('selectionStart' in this.oTextHandle)
|
Chris@76
|
970 var sCurrentText = this.oTextHandle.value.substr(this.oTextHandle.selectionStart, (this.oTextHandle.selectionEnd - this.oTextHandle.selectionStart));
|
Chris@76
|
971
|
Chris@76
|
972 else
|
Chris@76
|
973 return;
|
Chris@76
|
974
|
Chris@76
|
975 // Do bits that are likely to have attributes.
|
Chris@76
|
976 sCurrentText = sCurrentText.replace(RegExp("\\[/?(url|img|iurl|ftp|email|img|color|font|size|list|bdo).*?\\]", "g"), '');
|
Chris@76
|
977 // Then just anything that looks like BBC.
|
Chris@76
|
978 sCurrentText = sCurrentText.replace(RegExp("\\[/?[A-Za-z]+\\]", "g"), '');
|
Chris@76
|
979
|
Chris@76
|
980 replaceText(sCurrentText, this.oTextHandle);
|
Chris@76
|
981 }
|
Chris@76
|
982 }
|
Chris@76
|
983
|
Chris@76
|
984 // Toggle wysiwyg/normal mode.
|
Chris@76
|
985 smc_Editor.prototype.toggleView = function(bView)
|
Chris@76
|
986 {
|
Chris@76
|
987 if (!this.bRichTextPossible)
|
Chris@76
|
988 {
|
Chris@76
|
989 alert(oEditorStrings['wont_work']);
|
Chris@76
|
990 return false;
|
Chris@76
|
991 }
|
Chris@76
|
992
|
Chris@76
|
993 // Overriding or alternating?
|
Chris@76
|
994 if (typeof(bView) == 'undefined')
|
Chris@76
|
995 bView = !this.bRichTextEnabled;
|
Chris@76
|
996
|
Chris@76
|
997 this.requestParsedMessage(bView);
|
Chris@76
|
998
|
Chris@76
|
999 return true;
|
Chris@76
|
1000 }
|
Chris@76
|
1001
|
Chris@76
|
1002 // Request the message in a different form.
|
Chris@76
|
1003 smc_Editor.prototype.requestParsedMessage = function(bView)
|
Chris@76
|
1004 {
|
Chris@76
|
1005 // Replace with a force reload.
|
Chris@76
|
1006 if (!window.XMLHttpRequest)
|
Chris@76
|
1007 {
|
Chris@76
|
1008 alert(oEditorStrings['func_disabled']);
|
Chris@76
|
1009 return;
|
Chris@76
|
1010 }
|
Chris@76
|
1011
|
Chris@76
|
1012 // Get the text.
|
Chris@76
|
1013 var sText = this.getText(true, !bView).replace(/&#/g, "&#").php_to8bit().php_urlencode();
|
Chris@76
|
1014
|
Chris@76
|
1015 this.tmpMethod = sendXMLDocument;
|
Chris@76
|
1016 this.tmpMethod(smf_prepareScriptUrl(smf_scripturl) + 'action=jseditor;view=' + (bView ? 1 : 0) + ';' + this.opt.sSessionVar + '=' + this.opt.sSessionId + ';xml', 'message=' + sText, this.onToggleDataReceived);
|
Chris@76
|
1017 delete tmpMethod;
|
Chris@76
|
1018 }
|
Chris@76
|
1019
|
Chris@76
|
1020 smc_Editor.prototype.onToggleDataReceived = function(oXMLDoc)
|
Chris@76
|
1021 {
|
Chris@76
|
1022 var sText = '';
|
Chris@76
|
1023 for (var i = 0; i < oXMLDoc.getElementsByTagName('message')[0].childNodes.length; i++)
|
Chris@76
|
1024 sText += oXMLDoc.getElementsByTagName('message')[0].childNodes[i].nodeValue;
|
Chris@76
|
1025
|
Chris@76
|
1026 // What is this new view we have?
|
Chris@76
|
1027 this.bRichTextEnabled = oXMLDoc.getElementsByTagName('message')[0].getAttribute('view') != '0';
|
Chris@76
|
1028
|
Chris@76
|
1029 if (this.bRichTextEnabled)
|
Chris@76
|
1030 {
|
Chris@76
|
1031 this.oFrameHandle.style.display = '';
|
Chris@76
|
1032 if (this.showDebug)
|
Chris@76
|
1033 this.oBreadHandle.style.display = '';
|
Chris@76
|
1034 this.oTextHandle.style.display = 'none';
|
Chris@76
|
1035 }
|
Chris@76
|
1036 else
|
Chris@76
|
1037 {
|
Chris@76
|
1038 sText = sText.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
|
Chris@76
|
1039 this.oFrameHandle.style.display = 'none';
|
Chris@76
|
1040 this.oBreadHandle.style.display = 'none';
|
Chris@76
|
1041 this.oTextHandle.style.display = '';
|
Chris@76
|
1042 }
|
Chris@76
|
1043
|
Chris@76
|
1044 // First we focus.
|
Chris@76
|
1045 this.setFocus();
|
Chris@76
|
1046
|
Chris@76
|
1047 this.insertText(sText, true);
|
Chris@76
|
1048
|
Chris@76
|
1049 // Record the new status.
|
Chris@76
|
1050 document.getElementById(this.opt.sUniqueId + '_mode').value = this.bRichTextEnabled ? '1' : '0';
|
Chris@76
|
1051
|
Chris@76
|
1052 // Rebuild the bread crumb!
|
Chris@76
|
1053 this.updateEditorControls();
|
Chris@76
|
1054 }
|
Chris@76
|
1055
|
Chris@76
|
1056 // Set the focus for the editing window.
|
Chris@76
|
1057 smc_Editor.prototype.setFocus = function(force_both)
|
Chris@76
|
1058 {
|
Chris@76
|
1059 if (!this.bRichTextEnabled)
|
Chris@76
|
1060 this.oTextHandle.focus();
|
Chris@76
|
1061 else if (is_ff || is_opera)
|
Chris@76
|
1062 this.oFrameHandle.focus();
|
Chris@76
|
1063 else
|
Chris@76
|
1064 this.oFrameWindow.focus();
|
Chris@76
|
1065 }
|
Chris@76
|
1066
|
Chris@76
|
1067 // Start up the spellchecker!
|
Chris@76
|
1068 smc_Editor.prototype.spellCheckStart = function()
|
Chris@76
|
1069 {
|
Chris@76
|
1070 if (!spellCheck)
|
Chris@76
|
1071 return false;
|
Chris@76
|
1072
|
Chris@76
|
1073 // If we're in HTML mode we need to get the non-HTML text.
|
Chris@76
|
1074 if (this.bRichTextEnabled)
|
Chris@76
|
1075 {
|
Chris@76
|
1076 var sText = escape(this.getText(true, 1).php_to8bit());
|
Chris@76
|
1077
|
Chris@76
|
1078 this.tmpMethod = sendXMLDocument;
|
Chris@76
|
1079 this.tmpMethod(smf_prepareScriptUrl(smf_scripturl) + 'action=jseditor;view=0;' + this.opt.sSessionVar + '=' + this.opt.sSessionId + ';xml', 'message=' + sText, this.onSpellCheckDataReceived);
|
Chris@76
|
1080 delete tmpMethod;
|
Chris@76
|
1081 }
|
Chris@76
|
1082 // Otherwise start spellchecking right away.
|
Chris@76
|
1083 else
|
Chris@76
|
1084 spellCheck(this.sFormId, this.opt.sUniqueId);
|
Chris@76
|
1085
|
Chris@76
|
1086 return true;
|
Chris@76
|
1087 }
|
Chris@76
|
1088
|
Chris@76
|
1089 // This contains the spellcheckable text.
|
Chris@76
|
1090 smc_Editor.prototype.onSpellCheckDataReceived = function(oXMLDoc)
|
Chris@76
|
1091 {
|
Chris@76
|
1092 var sText = '';
|
Chris@76
|
1093 for (var i = 0; i < oXMLDoc.getElementsByTagName('message')[0].childNodes.length; i++)
|
Chris@76
|
1094 sText += oXMLDoc.getElementsByTagName('message')[0].childNodes[i].nodeValue;
|
Chris@76
|
1095
|
Chris@76
|
1096 sText = sText.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
|
Chris@76
|
1097
|
Chris@76
|
1098 this.oTextHandle.value = sText;
|
Chris@76
|
1099 spellCheck(this.sFormId, this.opt.sUniqueId);
|
Chris@76
|
1100 }
|
Chris@76
|
1101
|
Chris@76
|
1102 // Function called when the Spellchecker is finished and ready to pass back.
|
Chris@76
|
1103 smc_Editor.prototype.spellCheckEnd = function()
|
Chris@76
|
1104 {
|
Chris@76
|
1105 // If HTML edit put the text back!
|
Chris@76
|
1106 if (this.bRichTextEnabled)
|
Chris@76
|
1107 {
|
Chris@76
|
1108 var sText = escape(this.getText(true, 0).php_to8bit());
|
Chris@76
|
1109
|
Chris@76
|
1110 this.tmpMethod = sendXMLDocument;
|
Chris@76
|
1111 this.tmpMethod(smf_prepareScriptUrl(smf_scripturl) + 'action=jseditor;view=1;' + this.opt.sSessionVar + '=' + this.opt.sSessionId + ';xml', 'message=' + sText, smf_editorArray[this.iArrayPosition].onSpellCheckCompleteDataReceived);
|
Chris@76
|
1112 delete tmpMethod;
|
Chris@76
|
1113 }
|
Chris@76
|
1114 else
|
Chris@76
|
1115 this.setFocus();
|
Chris@76
|
1116 }
|
Chris@76
|
1117
|
Chris@76
|
1118 // The corrected text.
|
Chris@76
|
1119 smc_Editor.prototype.onSpellCheckCompleteDataReceived = function(oXMLDoc)
|
Chris@76
|
1120 {
|
Chris@76
|
1121 var sText = '';
|
Chris@76
|
1122 for (var i = 0; i < oXMLDoc.getElementsByTagName('message')[0].childNodes.length; i++)
|
Chris@76
|
1123 sText += oXMLDoc.getElementsByTagName('message')[0].childNodes[i].nodeValue;
|
Chris@76
|
1124
|
Chris@76
|
1125 this.insertText(sText, true);
|
Chris@76
|
1126 this.setFocus();
|
Chris@76
|
1127 }
|
Chris@76
|
1128
|
Chris@76
|
1129 smc_Editor.prototype.resizeTextArea = function(newHeight, newWidth, is_change)
|
Chris@76
|
1130 {
|
Chris@76
|
1131 // Work out what the new height is.
|
Chris@76
|
1132 if (is_change)
|
Chris@76
|
1133 {
|
Chris@76
|
1134 // We'll assume pixels but may not be.
|
Chris@76
|
1135 newHeight = this._calculateNewDimension(this.oTextHandle.style.height, newHeight);
|
Chris@76
|
1136 if (newWidth)
|
Chris@76
|
1137 newWidth = this._calculateNewDimension(this.oTextHandle.style.width, newWidth);
|
Chris@76
|
1138 }
|
Chris@76
|
1139
|
Chris@76
|
1140 // Do the HTML editor - but only if it's enabled!
|
Chris@76
|
1141 if (this.bRichTextPossible)
|
Chris@76
|
1142 {
|
Chris@76
|
1143 this.oFrameHandle.style.height = newHeight;
|
Chris@76
|
1144 if (newWidth)
|
Chris@76
|
1145 this.oFrameHandle.style.width = newWidth;
|
Chris@76
|
1146 }
|
Chris@76
|
1147 // Do the text box regardless!
|
Chris@76
|
1148 this.oTextHandle.style.height = newHeight;
|
Chris@76
|
1149 if (newWidth)
|
Chris@76
|
1150 this.oTextHandle.style.width = newWidth;
|
Chris@76
|
1151 }
|
Chris@76
|
1152
|
Chris@76
|
1153 // A utility instruction to save repetition when trying to work out what to change on a height/width.
|
Chris@76
|
1154 smc_Editor.prototype._calculateNewDimension = function(old_size, change_size)
|
Chris@76
|
1155 {
|
Chris@76
|
1156 // We'll assume pixels but may not be.
|
Chris@76
|
1157 changeReg = change_size.toString().match(/(-)?(\d+)(\D*)/);
|
Chris@76
|
1158 curReg = old_size.toString().match(/(\d+)(\D*)/);
|
Chris@76
|
1159
|
Chris@76
|
1160 if (!changeReg[3])
|
Chris@76
|
1161 changeReg[3] = 'px';
|
Chris@76
|
1162
|
Chris@76
|
1163 if (changeReg[1] == '-')
|
Chris@76
|
1164 changeReg[2] = 0 - changeReg[2];
|
Chris@76
|
1165
|
Chris@76
|
1166 // Both the same type?
|
Chris@76
|
1167 if (changeReg[3] == curReg[2])
|
Chris@76
|
1168 {
|
Chris@76
|
1169 new_size = parseInt(changeReg[2]) + parseInt(curReg[1]);
|
Chris@76
|
1170 if (new_size < 50)
|
Chris@76
|
1171 new_size = 50;
|
Chris@76
|
1172 new_size = new_size.toString() + changeReg[3];
|
Chris@76
|
1173 }
|
Chris@76
|
1174 // Is the change a percentage?
|
Chris@76
|
1175 else if (changeReg[3] == '%')
|
Chris@76
|
1176 new_size = (parseInt(curReg[1]) + parseInt((parseInt(changeReg[2]) * parseInt(curReg[1])) / 100)).toString() + 'px';
|
Chris@76
|
1177 // Otherwise just guess!
|
Chris@76
|
1178 else
|
Chris@76
|
1179 new_size = (parseInt(curReg[1]) + (parseInt(changeReg[2]) / 10)).toString() + '%';
|
Chris@76
|
1180
|
Chris@76
|
1181 return new_size;
|
Chris@76
|
1182 }
|
Chris@76
|
1183
|
Chris@76
|
1184 // Register default keyboard shortcuts.
|
Chris@76
|
1185 smc_Editor.prototype.registerDefaultShortcuts = function()
|
Chris@76
|
1186 {
|
Chris@76
|
1187 if (is_ff)
|
Chris@76
|
1188 {
|
Chris@76
|
1189 this.registerShortcut('b', 'ctrl', 'b');
|
Chris@76
|
1190 this.registerShortcut('u', 'ctrl', 'u');
|
Chris@76
|
1191 this.registerShortcut('i', 'ctrl', 'i');
|
Chris@76
|
1192 this.registerShortcut('p', 'alt', 'preview');
|
Chris@76
|
1193 this.registerShortcut('s', 'alt', 'submit');
|
Chris@76
|
1194 }
|
Chris@76
|
1195 }
|
Chris@76
|
1196
|
Chris@76
|
1197 // Register a keyboard shortcut.
|
Chris@76
|
1198 smc_Editor.prototype.registerShortcut = function(sLetter, sModifiers, sCodeName)
|
Chris@76
|
1199 {
|
Chris@76
|
1200 if (!sCodeName)
|
Chris@76
|
1201 return;
|
Chris@76
|
1202
|
Chris@76
|
1203 var oNewShortcut = {
|
Chris@76
|
1204 code : sCodeName,
|
Chris@76
|
1205 key: sLetter.toUpperCase().charCodeAt(0),
|
Chris@76
|
1206 alt : false,
|
Chris@76
|
1207 ctrl : false
|
Chris@76
|
1208 };
|
Chris@76
|
1209
|
Chris@76
|
1210 var aSplitModifiers = sModifiers.split(',');
|
Chris@76
|
1211 for(var i = 0, n = aSplitModifiers.length; i < n; i++)
|
Chris@76
|
1212 if (aSplitModifiers[i] in oNewShortcut)
|
Chris@76
|
1213 oNewShortcut[aSplitModifiers[i]] = true;
|
Chris@76
|
1214
|
Chris@76
|
1215 this.aKeyboardShortcuts[this.aKeyboardShortcuts.length] = oNewShortcut;
|
Chris@76
|
1216 }
|
Chris@76
|
1217
|
Chris@76
|
1218 // Check whether the key has triggered a shortcut?
|
Chris@76
|
1219 smc_Editor.prototype.checkShortcut = function(oEvent)
|
Chris@76
|
1220 {
|
Chris@76
|
1221 // To be a shortcut it needs to be one of these, duh!
|
Chris@76
|
1222 if (!oEvent.altKey && !oEvent.ctrlKey)
|
Chris@76
|
1223 return false;
|
Chris@76
|
1224
|
Chris@76
|
1225 var sReturnCode = false;
|
Chris@76
|
1226
|
Chris@76
|
1227 // Let's take a look at each of our shortcuts shall we?
|
Chris@76
|
1228 for (var i = 0, n = this.aKeyboardShortcuts.length; i < n; i++)
|
Chris@76
|
1229 {
|
Chris@76
|
1230 // Found something?
|
Chris@76
|
1231 if (oEvent.altKey == this.aKeyboardShortcuts[i].alt && oEvent.ctrlKey == this.aKeyboardShortcuts[i].ctrl && oEvent.keyCode == this.aKeyboardShortcuts[i].key)
|
Chris@76
|
1232 sReturnCode = this.aKeyboardShortcuts[i].code;
|
Chris@76
|
1233 }
|
Chris@76
|
1234
|
Chris@76
|
1235 return sReturnCode;
|
Chris@76
|
1236 }
|
Chris@76
|
1237
|
Chris@76
|
1238 // The actual event check for the above!
|
Chris@76
|
1239 smc_Editor.prototype.shortcutCheck = function(oEvent)
|
Chris@76
|
1240 {
|
Chris@76
|
1241 var sFoundCode = this.checkShortcut(oEvent);
|
Chris@76
|
1242
|
Chris@76
|
1243 // Run it and exit.
|
Chris@76
|
1244 if (typeof(sFoundCode) == 'string' && sFoundCode != '')
|
Chris@76
|
1245 {
|
Chris@76
|
1246 var bCancelEvent = false;
|
Chris@76
|
1247 if (sFoundCode == 'submit')
|
Chris@76
|
1248 {
|
Chris@76
|
1249 // So much to do!
|
Chris@76
|
1250 var oForm = document.getElementById(this.sFormId);
|
Chris@76
|
1251 submitThisOnce(oForm);
|
Chris@76
|
1252 submitonce(oForm);
|
Chris@76
|
1253 smc_saveEntities(oForm.name, ['subject', this.opt.sUniqueId, 'guestname', 'evtitle', 'question']);
|
Chris@76
|
1254 oForm.submit();
|
Chris@76
|
1255
|
Chris@76
|
1256 bCancelEvent = true;
|
Chris@76
|
1257 }
|
Chris@76
|
1258 else if (sFoundCode == 'preview')
|
Chris@76
|
1259 {
|
Chris@76
|
1260 previewPost();
|
Chris@76
|
1261 bCancelEvent = true;
|
Chris@76
|
1262 }
|
Chris@76
|
1263 else
|
Chris@76
|
1264 bCancelEvent = this.opt.oBBCBox.emulateClick(sFoundCode);
|
Chris@76
|
1265
|
Chris@76
|
1266 if (bCancelEvent)
|
Chris@76
|
1267 {
|
Chris@76
|
1268 if (is_ie && oEvent.cancelBubble)
|
Chris@76
|
1269 oEvent.cancelBubble = true;
|
Chris@76
|
1270
|
Chris@76
|
1271 else if (oEvent.stopPropagation)
|
Chris@76
|
1272 {
|
Chris@76
|
1273 oEvent.stopPropagation();
|
Chris@76
|
1274 oEvent.preventDefault();
|
Chris@76
|
1275 }
|
Chris@76
|
1276
|
Chris@76
|
1277 return false;
|
Chris@76
|
1278 }
|
Chris@76
|
1279 }
|
Chris@76
|
1280
|
Chris@76
|
1281 return true;
|
Chris@76
|
1282 }
|
Chris@76
|
1283
|
Chris@76
|
1284 // This is the method called after clicking the resize bar.
|
Chris@76
|
1285 smc_Editor.prototype.startResize = function(oEvent)
|
Chris@76
|
1286 {
|
Chris@76
|
1287 if ('event' in window)
|
Chris@76
|
1288 oEvent = window.event;
|
Chris@76
|
1289
|
Chris@76
|
1290 if (!oEvent || window.smf_oCurrentResizeEditor != null)
|
Chris@76
|
1291 return true;
|
Chris@76
|
1292
|
Chris@76
|
1293 window.smf_oCurrentResizeEditor = this.iArrayPosition;
|
Chris@76
|
1294
|
Chris@76
|
1295 var aCurCoordinates = smf_mousePose(oEvent);
|
Chris@76
|
1296 this.osmc_EditorCurrentResize.old_y = aCurCoordinates[1];
|
Chris@76
|
1297 this.osmc_EditorCurrentResize.old_rel_y = null;
|
Chris@76
|
1298 this.osmc_EditorCurrentResize.cur_height = parseInt(this.oTextHandle.style.height);
|
Chris@76
|
1299
|
Chris@76
|
1300 // Set the necessary events for resizing.
|
Chris@76
|
1301 var oResizeEntity = is_ie ? document : window;
|
Chris@76
|
1302 oResizeEntity.addEventListener('mousemove', this.aEventWrappers.resizeOverDocument, false);
|
Chris@76
|
1303
|
Chris@76
|
1304 if (this.bRichTextPossible)
|
Chris@76
|
1305 this.oFrameDocument.addEventListener('mousemove', this.aEventWrappers.resizeOverIframe, false);
|
Chris@76
|
1306
|
Chris@76
|
1307 document.addEventListener('mouseup', this.aEventWrappers.endResize, true);
|
Chris@76
|
1308
|
Chris@76
|
1309 if (this.bRichTextPossible)
|
Chris@76
|
1310 this.oFrameDocument.addEventListener('mouseup', this.aEventWrappers.endResize, true);
|
Chris@76
|
1311
|
Chris@76
|
1312 return false;
|
Chris@76
|
1313 }
|
Chris@76
|
1314
|
Chris@76
|
1315 // This is kind of a cheat, as it only works over the IFRAME.
|
Chris@76
|
1316 smc_Editor.prototype.resizeOverIframe = function(oEvent)
|
Chris@76
|
1317 {
|
Chris@76
|
1318 if ('event' in window)
|
Chris@76
|
1319 oEvent = window.event;
|
Chris@76
|
1320
|
Chris@76
|
1321 if (!oEvent || window.smf_oCurrentResizeEditor == null)
|
Chris@76
|
1322 return true;
|
Chris@76
|
1323
|
Chris@76
|
1324 var newCords = smf_mousePose(oEvent);
|
Chris@76
|
1325
|
Chris@76
|
1326 if (this.osmc_EditorCurrentResize.old_rel_y == null)
|
Chris@76
|
1327 this.osmc_EditorCurrentResize.old_rel_y = newCords[1];
|
Chris@76
|
1328 else
|
Chris@76
|
1329 {
|
Chris@76
|
1330 var iNewHeight = newCords[1] - this.osmc_EditorCurrentResize.old_rel_y + this.osmc_EditorCurrentResize.cur_height;
|
Chris@76
|
1331 if (iNewHeight < 0)
|
Chris@76
|
1332 this.endResize();
|
Chris@76
|
1333 else
|
Chris@76
|
1334 this.resizeTextArea(iNewHeight + 'px', 0, false);
|
Chris@76
|
1335 }
|
Chris@76
|
1336
|
Chris@76
|
1337 return false;
|
Chris@76
|
1338 }
|
Chris@76
|
1339
|
Chris@76
|
1340 // This resizes an editor.
|
Chris@76
|
1341 smc_Editor.prototype.resizeOverDocument = function (oEvent)
|
Chris@76
|
1342 {
|
Chris@76
|
1343 if ('event' in window)
|
Chris@76
|
1344 oEvent = window.event;
|
Chris@76
|
1345
|
Chris@76
|
1346 if (!oEvent || window.smf_oCurrentResizeEditor == null)
|
Chris@76
|
1347 return true;
|
Chris@76
|
1348
|
Chris@76
|
1349 var newCords = smf_mousePose(oEvent);
|
Chris@76
|
1350
|
Chris@76
|
1351 var iNewHeight = newCords[1] - this.osmc_EditorCurrentResize.old_y + this.osmc_EditorCurrentResize.cur_height;
|
Chris@76
|
1352 if (iNewHeight < 0)
|
Chris@76
|
1353 this.endResize();
|
Chris@76
|
1354 else
|
Chris@76
|
1355 this.resizeTextArea(iNewHeight + 'px', 0, false);
|
Chris@76
|
1356
|
Chris@76
|
1357 return false;
|
Chris@76
|
1358 }
|
Chris@76
|
1359
|
Chris@76
|
1360 smc_Editor.prototype.endResize = function (oEvent)
|
Chris@76
|
1361 {
|
Chris@76
|
1362 if ('event' in window)
|
Chris@76
|
1363 oEvent = window.event;
|
Chris@76
|
1364
|
Chris@76
|
1365 if (window.smf_oCurrentResizeEditor == null)
|
Chris@76
|
1366 return true;
|
Chris@76
|
1367
|
Chris@76
|
1368 window.smf_oCurrentResizeEditor = null;
|
Chris@76
|
1369
|
Chris@76
|
1370 // Remove the event...
|
Chris@76
|
1371 var oResizeEntity = is_ie ? document : window;
|
Chris@76
|
1372 oResizeEntity.removeEventListener('mousemove', this.aEventWrappers.resizeOverDocument, false);
|
Chris@76
|
1373
|
Chris@76
|
1374 if (this.bRichTextPossible)
|
Chris@76
|
1375 this.oFrameDocument.removeEventListener('mousemove', this.aEventWrappers.resizeOverIframe, false);
|
Chris@76
|
1376
|
Chris@76
|
1377 document.removeEventListener('mouseup', this.aEventWrappers.endResize, true);
|
Chris@76
|
1378
|
Chris@76
|
1379 if (this.bRichTextPossible)
|
Chris@76
|
1380 this.oFrameDocument.removeEventListener('mouseup', this.aEventWrappers.endResize, true);
|
Chris@76
|
1381
|
Chris@76
|
1382 return false;
|
Chris@76
|
1383 }
|
Chris@76
|
1384
|
Chris@76
|
1385 // *** smc_SmileyBox class.
|
Chris@76
|
1386 function smc_SmileyBox(oOptions)
|
Chris@76
|
1387 {
|
Chris@76
|
1388 this.opt = oOptions;
|
Chris@76
|
1389 this.oSmileyRowsContent = {};
|
Chris@76
|
1390 this.oSmileyPopupWindow = null;
|
Chris@76
|
1391 this.init();
|
Chris@76
|
1392 }
|
Chris@76
|
1393
|
Chris@76
|
1394 smc_SmileyBox.prototype.init = function ()
|
Chris@76
|
1395 {
|
Chris@76
|
1396 // Get the HTML content of the smileys visible on the post screen.
|
Chris@76
|
1397 this.getSmileyRowsContent('postform');
|
Chris@76
|
1398
|
Chris@76
|
1399 // Inject the HTML.
|
Chris@76
|
1400 setInnerHTML(document.getElementById(this.opt.sContainerDiv), this.opt.sSmileyBoxTemplate.easyReplace({
|
Chris@76
|
1401 smileyRows: this.oSmileyRowsContent.postform,
|
Chris@76
|
1402 moreSmileys: this.opt.oSmileyLocations.popup.length == 0 ? '' : this.opt.sMoreSmileysTemplate.easyReplace({
|
Chris@76
|
1403 moreSmileysId: this.opt.sUniqueId + '_addMoreSmileys'
|
Chris@76
|
1404 })
|
Chris@76
|
1405 }));
|
Chris@76
|
1406
|
Chris@76
|
1407 // Initialize the smileys.
|
Chris@76
|
1408 this.initSmileys('postform', document);
|
Chris@76
|
1409
|
Chris@76
|
1410 // Initialize the [more] button.
|
Chris@76
|
1411 if (this.opt.oSmileyLocations.popup.length > 0)
|
Chris@76
|
1412 {
|
Chris@76
|
1413 var oMoreLink = document.getElementById(this.opt.sUniqueId + '_addMoreSmileys');
|
Chris@76
|
1414 oMoreLink.instanceRef = this;
|
Chris@76
|
1415 oMoreLink.onclick = function () {
|
Chris@76
|
1416 this.instanceRef.handleShowMoreSmileys();
|
Chris@76
|
1417 return false;
|
Chris@76
|
1418 }
|
Chris@76
|
1419 }
|
Chris@76
|
1420 }
|
Chris@76
|
1421
|
Chris@76
|
1422 // Loop through the smileys to setup the HTML.
|
Chris@76
|
1423 smc_SmileyBox.prototype.getSmileyRowsContent = function (sLocation)
|
Chris@76
|
1424 {
|
Chris@76
|
1425 // If it's already defined, don't bother.
|
Chris@76
|
1426 if (sLocation in this.oSmileyRowsContent)
|
Chris@76
|
1427 return;
|
Chris@76
|
1428
|
Chris@76
|
1429 this.oSmileyRowsContent[sLocation] = '';
|
Chris@76
|
1430
|
Chris@76
|
1431 for (var iSmileyRowIndex = 0, iSmileyRowCount = this.opt.oSmileyLocations[sLocation].length; iSmileyRowIndex < iSmileyRowCount; iSmileyRowIndex++)
|
Chris@76
|
1432 {
|
Chris@76
|
1433 var sSmileyRowContent = '';
|
Chris@76
|
1434 for (var iSmileyIndex = 0, iSmileyCount = this.opt.oSmileyLocations[sLocation][iSmileyRowIndex].length; iSmileyIndex < iSmileyCount; iSmileyIndex++)
|
Chris@76
|
1435 sSmileyRowContent += this.opt.sSmileyTemplate.easyReplace({
|
Chris@76
|
1436 smileySource: this.opt.oSmileyLocations[sLocation][iSmileyRowIndex][iSmileyIndex].sSrc.php_htmlspecialchars(),
|
Chris@76
|
1437 smileyDescription: this.opt.oSmileyLocations[sLocation][iSmileyRowIndex][iSmileyIndex].sDescription.php_htmlspecialchars(),
|
Chris@76
|
1438 smileyCode: this.opt.oSmileyLocations[sLocation][iSmileyRowIndex][iSmileyIndex].sCode.php_htmlspecialchars(),
|
Chris@76
|
1439 smileyId: this.opt.sUniqueId + '_' + sLocation + '_' + iSmileyRowIndex.toString() + '_' + iSmileyIndex.toString()
|
Chris@76
|
1440 });
|
Chris@76
|
1441
|
Chris@76
|
1442 this.oSmileyRowsContent[sLocation] += this.opt.sSmileyRowTemplate.easyReplace({
|
Chris@76
|
1443 smileyRow: sSmileyRowContent
|
Chris@76
|
1444 });
|
Chris@76
|
1445 }
|
Chris@76
|
1446 }
|
Chris@76
|
1447
|
Chris@76
|
1448 smc_SmileyBox.prototype.initSmileys = function (sLocation, oDocument)
|
Chris@76
|
1449 {
|
Chris@76
|
1450 for (var iSmileyRowIndex = 0, iSmileyRowCount = this.opt.oSmileyLocations[sLocation].length; iSmileyRowIndex < iSmileyRowCount; iSmileyRowIndex++)
|
Chris@76
|
1451 {
|
Chris@76
|
1452 for (var iSmileyIndex = 0, iSmileyCount = this.opt.oSmileyLocations[sLocation][iSmileyRowIndex].length; iSmileyIndex < iSmileyCount; iSmileyIndex++)
|
Chris@76
|
1453 {
|
Chris@76
|
1454 var oSmiley = oDocument.getElementById(this.opt.sUniqueId + '_' + sLocation + '_' + iSmileyRowIndex.toString() + '_' + iSmileyIndex.toString());
|
Chris@76
|
1455 oSmiley.instanceRef = this;
|
Chris@76
|
1456 oSmiley.style.cursor = 'pointer';
|
Chris@76
|
1457 oSmiley.onclick = function () {
|
Chris@76
|
1458 this.instanceRef.clickHandler(this);
|
Chris@76
|
1459 return false;
|
Chris@76
|
1460 }
|
Chris@76
|
1461 }
|
Chris@76
|
1462 }
|
Chris@76
|
1463 }
|
Chris@76
|
1464
|
Chris@76
|
1465 smc_SmileyBox.prototype.clickHandler = function (oSmileyImg)
|
Chris@76
|
1466 {
|
Chris@76
|
1467 // Dissect the id...
|
Chris@76
|
1468 var aMatches = oSmileyImg.id.match(/([^_]+)_(\d+)_(\d+)$/);
|
Chris@76
|
1469 if (aMatches.length != 4)
|
Chris@76
|
1470 return false;
|
Chris@76
|
1471
|
Chris@76
|
1472 // ...to determine its exact smiley properties.
|
Chris@76
|
1473 var sLocation = aMatches[1];
|
Chris@76
|
1474 var iSmileyRowIndex = aMatches[2];
|
Chris@76
|
1475 var iSmileyIndex = aMatches[3];
|
Chris@76
|
1476 var oProperties = this.opt.oSmileyLocations[sLocation][iSmileyRowIndex][iSmileyIndex];
|
Chris@76
|
1477
|
Chris@76
|
1478 if ('sClickHandler' in this.opt)
|
Chris@76
|
1479 eval(this.opt.sClickHandler + '(oProperties)');
|
Chris@76
|
1480
|
Chris@76
|
1481 return false;
|
Chris@76
|
1482 }
|
Chris@76
|
1483
|
Chris@76
|
1484 smc_SmileyBox.prototype.handleShowMoreSmileys = function ()
|
Chris@76
|
1485 {
|
Chris@76
|
1486 // Focus the window if it's already opened.
|
Chris@76
|
1487 if (this.oSmileyPopupWindow != null && 'closed' in this.oSmileyPopupWindow && !this.oSmileyPopupWindow.closed)
|
Chris@76
|
1488 {
|
Chris@76
|
1489 this.oSmileyPopupWindow.focus();
|
Chris@76
|
1490 return;
|
Chris@76
|
1491 }
|
Chris@76
|
1492
|
Chris@76
|
1493 // Get the smiley HTML.
|
Chris@76
|
1494 this.getSmileyRowsContent('popup');
|
Chris@76
|
1495
|
Chris@76
|
1496 // Open the popup.
|
Chris@76
|
1497 this.oSmileyPopupWindow = window.open('about:blank', this.opt.sUniqueId + '_addMoreSmileysPopup', 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,width=480,height=220,resizable=yes');
|
Chris@76
|
1498
|
Chris@76
|
1499 // Paste the template in the popup.
|
Chris@76
|
1500 this.oSmileyPopupWindow.document.open('text/html', 'replace');
|
Chris@76
|
1501 this.oSmileyPopupWindow.document.write(this.opt.sMoreSmileysPopupTemplate.easyReplace({
|
Chris@76
|
1502 smileyRows: this.oSmileyRowsContent.popup,
|
Chris@76
|
1503 moreSmileysCloseLinkId: this.opt.sUniqueId + '_closeMoreSmileys'
|
Chris@76
|
1504 }));
|
Chris@76
|
1505 this.oSmileyPopupWindow.document.close();
|
Chris@76
|
1506
|
Chris@76
|
1507 // Initialize the smileys that are in the popup window.
|
Chris@76
|
1508 this.initSmileys('popup', this.oSmileyPopupWindow.document);
|
Chris@76
|
1509
|
Chris@76
|
1510 // Add a function to the close window button.
|
Chris@76
|
1511 var aCloseLink = this.oSmileyPopupWindow.document.getElementById(this.opt.sUniqueId + '_closeMoreSmileys');
|
Chris@76
|
1512 aCloseLink.instanceRef = this;
|
Chris@76
|
1513 aCloseLink.onclick = function () {
|
Chris@76
|
1514 this.instanceRef.oSmileyPopupWindow.close();
|
Chris@76
|
1515 return false;
|
Chris@76
|
1516 }
|
Chris@76
|
1517 }
|
Chris@76
|
1518
|
Chris@76
|
1519
|
Chris@76
|
1520 // *** smc_BBCButtonBox class.
|
Chris@76
|
1521 function smc_BBCButtonBox(oOptions)
|
Chris@76
|
1522 {
|
Chris@76
|
1523 this.opt = oOptions;
|
Chris@76
|
1524 this.init();
|
Chris@76
|
1525 }
|
Chris@76
|
1526
|
Chris@76
|
1527 smc_BBCButtonBox.prototype.init = function ()
|
Chris@76
|
1528 {
|
Chris@76
|
1529 var sBbcContent = '';
|
Chris@76
|
1530 for (var iButtonRowIndex = 0, iRowCount = this.opt.aButtonRows.length; iButtonRowIndex < iRowCount; iButtonRowIndex++)
|
Chris@76
|
1531 {
|
Chris@76
|
1532 var sRowContent = '';
|
Chris@76
|
1533 var bPreviousWasDivider = false;
|
Chris@76
|
1534 for (var iButtonIndex = 0, iButtonCount = this.opt.aButtonRows[iButtonRowIndex].length; iButtonIndex < iButtonCount; iButtonIndex++)
|
Chris@76
|
1535 {
|
Chris@76
|
1536 var oCurButton = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1537 switch (oCurButton.sType)
|
Chris@76
|
1538 {
|
Chris@76
|
1539 case 'button':
|
Chris@76
|
1540 if (oCurButton.bEnabled)
|
Chris@76
|
1541 {
|
Chris@76
|
1542 sRowContent += this.opt.sButtonTemplate.easyReplace({
|
Chris@76
|
1543 buttonId: this.opt.sUniqueId.php_htmlspecialchars() + '_button_' + iButtonRowIndex.toString() + '_' + iButtonIndex.toString(),
|
Chris@76
|
1544 buttonSrc: oCurButton.sImage.php_htmlspecialchars(),
|
Chris@76
|
1545 buttonDescription: oCurButton.sDescription.php_htmlspecialchars()
|
Chris@76
|
1546 });
|
Chris@76
|
1547
|
Chris@76
|
1548 bPreviousWasDivider = false;
|
Chris@76
|
1549 }
|
Chris@76
|
1550 break;
|
Chris@76
|
1551
|
Chris@76
|
1552 case 'divider':
|
Chris@76
|
1553 if (!bPreviousWasDivider)
|
Chris@76
|
1554 sRowContent += this.opt.sDividerTemplate;
|
Chris@76
|
1555
|
Chris@76
|
1556 bPreviousWasDivider = true;
|
Chris@76
|
1557 break;
|
Chris@76
|
1558
|
Chris@76
|
1559 case 'select':
|
Chris@76
|
1560 var sOptions = '';
|
Chris@76
|
1561
|
Chris@76
|
1562 // Fighting javascript's idea of order in a for loop... :P
|
Chris@76
|
1563 if ('' in oCurButton.oOptions)
|
Chris@76
|
1564 sOptions = '<option value="">' + oCurButton.oOptions[''].php_htmlspecialchars() + '</option>';
|
Chris@76
|
1565 for (var sSelectValue in oCurButton.oOptions)
|
Chris@76
|
1566 // we've been through this before
|
Chris@76
|
1567 if (sSelectValue != '')
|
Chris@76
|
1568 sOptions += '<option value="' + sSelectValue.php_htmlspecialchars() + '">' + oCurButton.oOptions[sSelectValue].php_htmlspecialchars() + '</option>';
|
Chris@76
|
1569
|
Chris@76
|
1570 sRowContent += this.opt.sSelectTemplate.easyReplace({
|
Chris@76
|
1571 selectName: oCurButton.sName,
|
Chris@76
|
1572 selectId: this.opt.sUniqueId.php_htmlspecialchars() + '_select_' + iButtonRowIndex.toString() + '_' + iButtonIndex.toString(),
|
Chris@76
|
1573 selectOptions: sOptions
|
Chris@76
|
1574 });
|
Chris@76
|
1575
|
Chris@76
|
1576 bPreviousWasDivider = false;
|
Chris@76
|
1577 break;
|
Chris@76
|
1578 }
|
Chris@76
|
1579 }
|
Chris@76
|
1580 sBbcContent += this.opt.sButtonRowTemplate.easyReplace({
|
Chris@76
|
1581 buttonRow: sRowContent
|
Chris@76
|
1582 });
|
Chris@76
|
1583 }
|
Chris@76
|
1584
|
Chris@76
|
1585 var oBbcContainer = document.getElementById(this.opt.sContainerDiv);
|
Chris@76
|
1586 setInnerHTML(oBbcContainer, sBbcContent);
|
Chris@76
|
1587
|
Chris@76
|
1588 for (var iButtonRowIndex = 0, iRowCount = this.opt.aButtonRows.length; iButtonRowIndex < iRowCount; iButtonRowIndex++)
|
Chris@76
|
1589 {
|
Chris@76
|
1590 for (var iButtonIndex = 0, iButtonCount = this.opt.aButtonRows[iButtonRowIndex].length; iButtonIndex < iButtonCount; iButtonIndex++)
|
Chris@76
|
1591 {
|
Chris@76
|
1592 var oCurControl = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1593 switch (oCurControl.sType)
|
Chris@76
|
1594 {
|
Chris@76
|
1595 case 'button':
|
Chris@76
|
1596 if (!oCurControl.bEnabled)
|
Chris@76
|
1597 break;
|
Chris@76
|
1598
|
Chris@76
|
1599 oCurControl.oImg = document.getElementById(this.opt.sUniqueId.php_htmlspecialchars() + '_button_' + iButtonRowIndex.toString() + '_' + iButtonIndex.toString());
|
Chris@76
|
1600 oCurControl.oImg.style.cursor = 'pointer';
|
Chris@76
|
1601 if ('sButtonBackgroundImage' in this.opt)
|
Chris@76
|
1602 oCurControl.oImg.style.backgroundImage = 'url(' + this.opt.sButtonBackgroundImage + ')';
|
Chris@76
|
1603
|
Chris@76
|
1604 oCurControl.oImg.instanceRef = this;
|
Chris@76
|
1605 oCurControl.oImg.onmouseover = function () {
|
Chris@76
|
1606 this.instanceRef.handleButtonMouseOver(this);
|
Chris@76
|
1607 };
|
Chris@76
|
1608 oCurControl.oImg.onmouseout = function () {
|
Chris@76
|
1609 this.instanceRef.handleButtonMouseOut(this);
|
Chris@76
|
1610 };
|
Chris@76
|
1611 oCurControl.oImg.onclick = function () {
|
Chris@76
|
1612 this.instanceRef.handleButtonClick(this);
|
Chris@76
|
1613 };
|
Chris@76
|
1614
|
Chris@76
|
1615 oCurControl.oImg.bIsActive = false;
|
Chris@76
|
1616 oCurControl.oImg.bHover = false;
|
Chris@76
|
1617 break;
|
Chris@76
|
1618
|
Chris@76
|
1619 case 'select':
|
Chris@76
|
1620 oCurControl.oSelect = document.getElementById(this.opt.sUniqueId.php_htmlspecialchars() + '_select_' + iButtonRowIndex.toString() + '_' + iButtonIndex.toString());
|
Chris@76
|
1621
|
Chris@76
|
1622 oCurControl.oSelect.instanceRef = this;
|
Chris@76
|
1623 oCurControl.oSelect.onchange = oCurControl.onchange = function () {
|
Chris@76
|
1624 this.instanceRef.handleSelectChange(this);
|
Chris@76
|
1625 }
|
Chris@76
|
1626 break;
|
Chris@76
|
1627 }
|
Chris@76
|
1628 }
|
Chris@76
|
1629 }
|
Chris@76
|
1630 }
|
Chris@76
|
1631
|
Chris@76
|
1632 smc_BBCButtonBox.prototype.handleButtonMouseOver = function (oButtonImg)
|
Chris@76
|
1633 {
|
Chris@76
|
1634 oButtonImg.bHover = true;
|
Chris@76
|
1635 this.updateButtonStatus(oButtonImg);
|
Chris@76
|
1636 }
|
Chris@76
|
1637
|
Chris@76
|
1638 smc_BBCButtonBox.prototype.handleButtonMouseOut = function (oButtonImg)
|
Chris@76
|
1639 {
|
Chris@76
|
1640 oButtonImg.bHover = false;
|
Chris@76
|
1641 this.updateButtonStatus(oButtonImg);
|
Chris@76
|
1642 }
|
Chris@76
|
1643
|
Chris@76
|
1644 smc_BBCButtonBox.prototype.updateButtonStatus = function (oButtonImg)
|
Chris@76
|
1645 {
|
Chris@76
|
1646 var sNewURL = '';
|
Chris@76
|
1647 if (oButtonImg.bHover && oButtonImg.bIsActive && 'sActiveButtonBackgroundImageHover' in this.opt)
|
Chris@76
|
1648 sNewURL = 'url(' + this.opt.sActiveButtonBackgroundImageHover + ')';
|
Chris@76
|
1649 else if (!oButtonImg.bHover && oButtonImg.bIsActive && 'sActiveButtonBackgroundImage' in this.opt)
|
Chris@76
|
1650 sNewURL = 'url(' + this.opt.sActiveButtonBackgroundImage + ')';
|
Chris@76
|
1651 else if (oButtonImg.bHover && 'sButtonBackgroundImageHover' in this.opt)
|
Chris@76
|
1652 sNewURL = 'url(' + this.opt.sButtonBackgroundImageHover + ')';
|
Chris@76
|
1653 else if ('sButtonBackgroundImage' in this.opt)
|
Chris@76
|
1654 sNewURL = 'url(' + this.opt.sButtonBackgroundImage + ')';
|
Chris@76
|
1655
|
Chris@76
|
1656 if (oButtonImg.style.backgroundImage != sNewURL)
|
Chris@76
|
1657 oButtonImg.style.backgroundImage = sNewURL;
|
Chris@76
|
1658 }
|
Chris@76
|
1659
|
Chris@76
|
1660 smc_BBCButtonBox.prototype.handleButtonClick = function (oButtonImg)
|
Chris@76
|
1661 {
|
Chris@76
|
1662 // Dissect the id attribute...
|
Chris@76
|
1663 var aMatches = oButtonImg.id.match(/(\d+)_(\d+)$/);
|
Chris@76
|
1664 if (aMatches.length != 3)
|
Chris@76
|
1665 return false;
|
Chris@76
|
1666
|
Chris@76
|
1667 // ...so that we can point to the exact button.
|
Chris@76
|
1668 var iButtonRowIndex = aMatches[1];
|
Chris@76
|
1669 var iButtonIndex = aMatches[2];
|
Chris@76
|
1670 var oProperties = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1671 oProperties.bIsActive = oButtonImg.bIsActive;
|
Chris@76
|
1672
|
Chris@76
|
1673 if ('sButtonClickHandler' in this.opt)
|
Chris@76
|
1674 eval(this.opt.sButtonClickHandler + '(oProperties)');
|
Chris@76
|
1675
|
Chris@76
|
1676 return false;
|
Chris@76
|
1677 }
|
Chris@76
|
1678
|
Chris@76
|
1679 smc_BBCButtonBox.prototype.handleSelectChange = function (oSelectControl)
|
Chris@76
|
1680 {
|
Chris@76
|
1681 // Dissect the id attribute...
|
Chris@76
|
1682 var aMatches = oSelectControl.id.match(/(\d+)_(\d+)$/);
|
Chris@76
|
1683 if (aMatches.length != 3)
|
Chris@76
|
1684 return false;
|
Chris@76
|
1685
|
Chris@76
|
1686 // ...so that we can point to the exact button.
|
Chris@76
|
1687 var iButtonRowIndex = aMatches[1];
|
Chris@76
|
1688 var iButtonIndex = aMatches[2];
|
Chris@76
|
1689 var oProperties = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1690
|
Chris@76
|
1691 if ('sSelectChangeHandler' in this.opt)
|
Chris@76
|
1692 eval(this.opt.sSelectChangeHandler + '(oProperties)');
|
Chris@76
|
1693
|
Chris@76
|
1694 return true;
|
Chris@76
|
1695 }
|
Chris@76
|
1696
|
Chris@76
|
1697 smc_BBCButtonBox.prototype.setActive = function (aButtons)
|
Chris@76
|
1698 {
|
Chris@76
|
1699 for (var iButtonRowIndex = 0, iRowCount = this.opt.aButtonRows.length; iButtonRowIndex < iRowCount; iButtonRowIndex++)
|
Chris@76
|
1700 {
|
Chris@76
|
1701 for (var iButtonIndex = 0, iButtonCount = this.opt.aButtonRows[iButtonRowIndex].length; iButtonIndex < iButtonCount; iButtonIndex++)
|
Chris@76
|
1702 {
|
Chris@76
|
1703 var oCurControl = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1704 if (oCurControl.sType == 'button' && oCurControl.bEnabled)
|
Chris@76
|
1705 {
|
Chris@76
|
1706 oCurControl.oImg.bIsActive = in_array(oCurControl.sCode, aButtons);
|
Chris@76
|
1707 this.updateButtonStatus(oCurControl.oImg);
|
Chris@76
|
1708 }
|
Chris@76
|
1709 }
|
Chris@76
|
1710 }
|
Chris@76
|
1711 }
|
Chris@76
|
1712
|
Chris@76
|
1713 smc_BBCButtonBox.prototype.emulateClick = function (sCode)
|
Chris@76
|
1714 {
|
Chris@76
|
1715 for (var iButtonRowIndex = 0, iRowCount = this.opt.aButtonRows.length; iButtonRowIndex < iRowCount; iButtonRowIndex++)
|
Chris@76
|
1716 {
|
Chris@76
|
1717 for (var iButtonIndex = 0, iButtonCount = this.opt.aButtonRows[iButtonRowIndex].length; iButtonIndex < iButtonCount; iButtonIndex++)
|
Chris@76
|
1718 {
|
Chris@76
|
1719 var oCurControl = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1720 if (oCurControl.sType == 'button' && oCurControl.sCode == sCode)
|
Chris@76
|
1721 {
|
Chris@76
|
1722 eval(this.opt.sButtonClickHandler + '(oCurControl)');
|
Chris@76
|
1723 return true;
|
Chris@76
|
1724 }
|
Chris@76
|
1725 }
|
Chris@76
|
1726 }
|
Chris@76
|
1727 return false;
|
Chris@76
|
1728 }
|
Chris@76
|
1729
|
Chris@76
|
1730 smc_BBCButtonBox.prototype.setSelect = function (sSelectName, sValue)
|
Chris@76
|
1731 {
|
Chris@76
|
1732 if (!('sButtonClickHandler' in this.opt))
|
Chris@76
|
1733 return;
|
Chris@76
|
1734
|
Chris@76
|
1735 for (var iButtonRowIndex = 0, iRowCount = this.opt.aButtonRows.length; iButtonRowIndex < iRowCount; iButtonRowIndex++)
|
Chris@76
|
1736 {
|
Chris@76
|
1737 for (var iButtonIndex = 0, iButtonCount = this.opt.aButtonRows[iButtonRowIndex].length; iButtonIndex < iButtonCount; iButtonIndex++)
|
Chris@76
|
1738 {
|
Chris@76
|
1739 var oCurControl = this.opt.aButtonRows[iButtonRowIndex][iButtonIndex];
|
Chris@76
|
1740 if (oCurControl.sType == 'select' && oCurControl.sName == sSelectName)
|
Chris@76
|
1741 oCurControl.oSelect.value = sValue;
|
Chris@76
|
1742 }
|
Chris@76
|
1743 }
|
Chris@76
|
1744 }
|