]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js
Wordpress 2.3.2
[autoinstalls/wordpress.git] / wp-includes / js / tinymce / plugins / spellchecker / editor_plugin.js
1 /**
2  * $Id: editor_plugin_src.js 289 2007-05-28 09:12:16Z spocke $
3  *
4  * @author Moxiecode
5  * @copyright Copyright © 2004-2006, Moxiecode Systems AB, All rights reserved.
6  */
7
8 tinyMCE.importPluginLanguagePack('spellchecker', 'en,fr,sv,nn,nb');
9
10 // Plucin static class
11 var TinyMCE_SpellCheckerPlugin = {
12         _contextMenu : new TinyMCE_Menu(),
13         _menu : new TinyMCE_Menu(),
14         _counter : 0,
15         _ajaxPage : '/tinyspell.php',
16
17         getInfo : function() {
18                 return {
19                         longname : 'Spellchecker PHP',
20                         author : 'Moxiecode Systems AB',
21                         authorurl : 'http://tinymce.moxiecode.com',
22                         infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker',
23                         version : "1.0.5"
24                 };
25         },
26
27         handleEvent : function(e) {
28                 var elm = tinyMCE.isMSIE ? e.srcElement : e.target;
29                 var inst = tinyMCE.selectedInstance, args = '';
30                 var self = TinyMCE_SpellCheckerPlugin;
31                 var cm = self._contextMenu;
32                 var p, p2, x, y, sx, sy, h, elm;
33
34                 // Handle click on word
35                 if ((e.type == "click" || e.type == "contextmenu") && elm) {
36                         do {
37                                 if (tinyMCE.getAttrib(elm, 'class') == "mceItemHiddenSpellWord") {
38                                         inst.spellCheckerElm = elm;
39
40                                         // Setup arguments
41                                         args += 'id=' + inst.editorId + "|" + (++self._counter);
42                                         args += '&cmd=suggest&check=' + encodeURIComponent(elm.innerHTML);
43                                         args += '&lang=' + escape(inst.spellCheckerLang);
44
45                                         elm = inst.spellCheckerElm;
46                                         p = tinyMCE.getAbsPosition(inst.iframeElement);
47                                         p2 = tinyMCE.getAbsPosition(elm);
48                                         h = parseInt(elm.offsetHeight);
49                                         sx = inst.getBody().scrollLeft;
50                                         sy = inst.getBody().scrollTop;
51                                         x = p.absLeft + p2.absLeft - sx;
52                                         y = p.absTop + p2.absTop - sy + h;
53
54                                         cm.clear();
55                                         cm.addTitle(tinyMCE.getLang('lang_spellchecker_wait', '', true));
56                                         cm.show();
57                                         cm.moveTo(x, y);
58
59                                         inst.selection.selectNode(elm, false, false);
60
61                                         self._sendAjax(self.baseURL + self._ajaxPage, self._ajaxResponse, 'post', args);
62
63                                         tinyMCE.cancelEvent(e);
64                                         return false;
65                                 }
66                         } while ((elm = elm.parentNode));
67                 }
68
69                 return true;
70         },
71
72         initInstance : function(inst) {
73                 var self = TinyMCE_SpellCheckerPlugin, m = self._menu, cm = self._contextMenu, e;
74
75                 tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/spellchecker/css/content.css");
76
77                 if (!tinyMCE.hasMenu('spellcheckercontextmenu')) {
78                         tinyMCE.importCSS(document, tinyMCE.baseURL + "/plugins/spellchecker/css/spellchecker.css");
79
80                         cm.init({drop_menu : false});
81                         tinyMCE.addMenu('spellcheckercontextmenu', cm);
82                 }
83
84                 if (!tinyMCE.hasMenu('spellcheckermenu')) {
85                         m.init({});
86                         tinyMCE.addMenu('spellcheckermenu', m);
87                 }
88
89         inst.spellCheckerLang = 'en';
90                 self._buildSettingsMenu(inst, null);
91
92                 e = self._getBlockBoxLayer(inst).create('div', 'mceBlockBox', document.getElementById(inst.editorId + '_parent'));
93                 self._getMsgBoxLayer(inst).create('div', 'mceMsgBox', document.getElementById(inst.editorId + '_parent'));
94         },
95
96         _getMsgBoxLayer : function(inst) {
97                 if (!inst.spellCheckerMsgBoxL)
98                         inst.spellCheckerMsgBoxL = new TinyMCE_Layer(inst.editorId + '_spellcheckerMsgBox', false);
99
100                 return inst.spellCheckerMsgBoxL;
101         },
102
103         _getBlockBoxLayer : function(inst) {
104                 if (!inst.spellCheckerBoxL)
105                         inst.spellCheckerBoxL = new TinyMCE_Layer(inst.editorId + '_spellcheckerBlockBox', false);
106
107                 return inst.spellCheckerBoxL;
108         },
109
110         _buildSettingsMenu : function(inst, lang) {
111                 var i, ar = tinyMCE.getParam('spellchecker_languages', '+English=en').split(','), p;
112                 var self = TinyMCE_SpellCheckerPlugin, m = self._menu, c;
113
114                 m.clear();
115                 m.addTitle(tinyMCE.getLang('lang_spellchecker_langs', '', true));
116
117                 for (i=0; i<ar.length; i++) {
118                         if (ar[i] != '') {
119                                 p = ar[i].split('=');
120                                 c = 'mceMenuCheckItem';
121
122                                 if (p[0].charAt(0) == '+') {
123                                         p[0] = p[0].substring(1);
124
125                                         if (lang == null) {
126                                                 c = 'mceMenuSelectedItem';
127                                                 inst.spellCheckerLang = p[1];
128                                         }
129                                 }
130
131                                 if (lang == p[1])
132                                         c = 'mceMenuSelectedItem';
133
134                                 m.add({text : p[0], js : "tinyMCE.execInstanceCommand('" + inst.editorId + "','mceSpellCheckerSetLang',false,'" + p[1] + "');", class_name : c});
135                         }
136                 }
137         },
138
139         setupContent : function(editor_id, body, doc) {
140                 TinyMCE_SpellCheckerPlugin._removeWords(doc, null, true);
141         },
142
143         getControlHTML : function(cn) {
144                 switch (cn) {
145                         case "spellchecker":
146                                 return TinyMCE_SpellCheckerPlugin._getMenuButtonHTML(cn, 'lang_spellchecker_desc', '{$pluginurl}/images/spellchecker.gif', 'lang_spellchecker_desc', 'mceSpellCheckerMenu', 'mceSpellCheck');
147                 }
148
149                 return "";
150         },
151
152         /**
153          * Returns the HTML code for a normal button control.
154          *
155          * @param {string} id Button control id, this will be the suffix for the element id, the prefix is the editor id.
156          * @param {string} lang Language variable key name to insert as the title/alt of the button image.
157          * @param {string} img Image URL to insert, {$themeurl} and {$pluginurl} will be replaced.
158          * @param {string} mlang Language variable key name to insert as the title/alt of the menu button image.
159          * @param {string} mid Menu by id to display when the menu button is pressed.
160          * @param {string} cmd Command to execute when the user clicks the button.
161          * @param {string} ui Optional user interface boolean for command.
162          * @param {string} val Optional value for command.
163          * @return HTML code for a normal button based in input information.
164          * @type string
165          */
166         _getMenuButtonHTML : function(id, lang, img, mlang, mid, cmd, ui, val) {
167                 var h = '', m, x;
168
169                 cmd = 'tinyMCE.hideMenus();tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
170
171                 if (typeof(ui) != "undefined" && ui != null)
172                         cmd += ',' + ui;
173
174                 if (typeof(val) != "undefined" && val != null)
175                         cmd += ",'" + val + "'";
176
177                 cmd += ');';
178
179                 // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
180                 if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isMSIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
181                         // Tiled button
182                         x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
183                         h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceButtonNormal" target="_self">';
184                         h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />';
185                         h += '<img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" onclick="' + mcmd + 'return false;" />';
186                         h += '</a>';
187                 } else {
188                         if (tinyMCE.isMSIE && !tinyMCE.isOpera)
189                                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE.plugins.spellchecker._menuButtonEvent(\'over\',this);" onmouseout="tinyMCE.plugins.spellchecker._menuButtonEvent(\'out\',this);">';
190                         else
191                                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';
192
193                         h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';
194                         h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';
195                         h += '<a href="#" onclick="tinyMCE.plugins.spellchecker._toggleMenu(\'{$editor_id}\',\'' + mid + '\');return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
196                         h += '</a></span>';
197                 }
198
199                 return h;
200         },
201
202         _menuButtonEvent : function(e, o) {
203                 var t = this;
204
205                 // Give IE some time since it's buggy!! :(
206                 window.setTimeout(function() {
207                         t._menuButtonEvent2(e, o);
208                 }, 1);
209         },
210
211         _menuButtonEvent2 : function(e, o) {
212                 if (o.className == 'mceMenuButtonFocus')
213                         return;
214
215                 if (e == 'over')
216                         o.className = o.className + ' mceMenuHover';
217                 else
218                         o.className = o.className.replace(/\s.*$/, '');
219         },
220
221         _toggleMenu : function(editor_id, id) {
222                 var self = TinyMCE_SpellCheckerPlugin;
223                 var e = document.getElementById(editor_id + '_spellchecker');
224                 var inst = tinyMCE.getInstanceById(editor_id);
225
226                 if (self._menu.isVisible()) {
227                         tinyMCE.hideMenus();
228                         return;
229                 }
230
231                 tinyMCE.lastMenuBtnClass = e.className.replace(/\s.*$/, '');
232                 tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButtonFocus');
233
234                 self._menu.moveRelativeTo(e, 'bl');
235                 self._menu.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? 0 : 1, -1);
236
237                 if (tinyMCE.isOpera)
238                         self._menu.moveBy(0, -2);
239
240         self._onMenuEvent(inst, self._menu, 'show');
241
242                 self._menu.show();
243
244                 tinyMCE.lastSelectedMenuBtn = editor_id + '_spellchecker';
245         },
246
247         _onMenuEvent : function(inst, m, n) {
248                 TinyMCE_SpellCheckerPlugin._buildSettingsMenu(inst, inst.spellCheckerLang);
249         },
250
251         execCommand : function(editor_id, element, command, user_interface, value) {
252                 var inst = tinyMCE.getInstanceById(editor_id), self = TinyMCE_SpellCheckerPlugin, args = '', co, bb, mb, nl, i, e, mbs;
253
254                 // Handle commands
255                 switch (command) {
256                         case "mceSpellCheck":
257                                 if (!inst.spellcheckerOn) {
258                                         inst.spellCheckerBookmark = inst.selection.getBookmark();
259
260                                         // Fix for IE bug: #1610184
261                                         if (tinyMCE.isRealIE)
262                                                 tinyMCE.setInnerHTML(inst.getBody(), inst.getBody().innerHTML);
263
264                                         // Setup arguments
265                                         args += 'id=' + inst.editorId + "|" + (++self._counter);
266                                         args += '&cmd=spell&check=' + encodeURIComponent(self._getWordList(inst.getBody())).replace(/\'/g, '%27');
267                                         args += '&lang=' + escape(inst.spellCheckerLang);
268
269                                         co = document.getElementById(inst.editorId + '_parent').firstChild;
270                                         bb = self._getBlockBoxLayer(inst);
271                                         bb.moveRelativeTo(co, 'tl');
272                                         bb.resizeTo(co.offsetWidth, co.offsetHeight);
273                                         bb.show();
274
275                                         // Setup message box
276                                         mb = self._getMsgBoxLayer(inst);
277                                         e = mb.getElement();
278
279                                         if (e.childNodes[0])
280                                                 e.removeChild(e.childNodes[0]);
281
282                                         mbs = document.createElement("span");
283                                         mbs.innerHTML = '<span>' + tinyMCE.getLang('lang_spellchecker_swait', '', true) + '</span>';
284                                         e.appendChild(mbs);
285
286                                         mb.show();
287                                         mb.moveRelativeTo(co, 'cc');
288
289                                         if (tinyMCE.isMSIE && !tinyMCE.isOpera) {
290                                                 nl = co.getElementsByTagName('select');
291                                                 for (i=0; i<nl.length; i++)
292                                                         nl[i].disabled = true;
293                                         }
294
295                                         inst.spellcheckerOn = true;
296                                         tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButtonSelected');
297
298                                         self._sendAjax(self.baseURL + self._ajaxPage, self._ajaxResponse, 'post', args);
299                                 } else {
300                                         self._removeWords(inst.getDoc());
301                                         inst.spellcheckerOn = false;
302                                         tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButton');
303                                 }
304
305                                 return true;
306
307                         case "mceSpellCheckReplace":
308                                 if (inst.spellCheckerElm)
309                                         tinyMCE.setOuterHTML(inst.spellCheckerElm, value);
310
311                                 self._checkDone(inst);
312                                 self._contextMenu.hide();
313                                 self._menu.hide();
314
315                                 return true;
316
317                         case "mceSpellCheckIgnore":
318                                 if (inst.spellCheckerElm)
319                                         self._removeWord(inst.spellCheckerElm);
320
321                                 self._checkDone(inst);
322                                 self._contextMenu.hide();
323                                 self._menu.hide();
324                                 return true;
325
326                         case "mceSpellCheckIgnoreAll":
327                                 if (inst.spellCheckerElm)
328                                         self._removeWords(inst.getDoc(), inst.spellCheckerElm.innerHTML);
329
330                                 self._checkDone(inst);
331                                 self._contextMenu.hide();
332                                 self._menu.hide();
333                                 return true;
334
335                         case "mceSpellCheckerSetLang":
336                                 tinyMCE.hideMenus();
337                                 inst.spellCheckerLang = value;
338                                 self._removeWords(inst.getDoc());
339                                 inst.spellcheckerOn = false;
340                                 tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButton');
341                                 return true;
342                 }
343
344                 // Pass to next handler in chain
345                 return false;
346         },
347
348         cleanup : function(type, content, inst) {
349                 switch (type) {
350                         case "get_from_editor_dom":
351                                 TinyMCE_SpellCheckerPlugin._removeWords(content, null, true);
352                                 inst.spellcheckerOn = false;
353                                 break;
354                 }
355
356                 return content;
357         },
358
359         // Private plugin specific methods
360
361         _displayUI : function(inst) {
362                 var self = TinyMCE_SpellCheckerPlugin;
363                 var bb = self._getBlockBoxLayer(inst);
364                 var mb = self._getMsgBoxLayer(inst);
365                 var nl, i;
366                 var co = document.getElementById(inst.editorId + '_parent').firstChild;
367
368                 if (tinyMCE.isMSIE && !tinyMCE.isOpera) {
369                         nl = co.getElementsByTagName('select');
370                         for (i=0; i<nl.length; i++)
371                                 nl[i].disabled = false;
372                 }
373
374                 bb.hide();
375
376                 // Boom, crash in FF if focus isn't else were
377                 // el.style.display='none' on a opacity element seems to crash it
378                 mb.hide();
379         },
380
381         _ajaxResponse : function(xml, text) {
382                 var el = xml ? xml.documentElement : null;
383                 var inst = tinyMCE.selectedInstance, self = TinyMCE_SpellCheckerPlugin;
384                 var cmd = el ? el.getAttribute("cmd") : null, err, id = el ? el.getAttribute("id") : null;
385
386                 if (id)
387                         inst = tinyMCE.getInstanceById(id.substring(0, id.indexOf('|')));
388
389                 // Workaround for crash in Gecko
390                 if (tinyMCE.isGecko)
391                         window.focus();
392
393                 self._displayUI(inst);
394
395                 // Restore the selection again
396                 if (tinyMCE.isGecko) {
397                         inst.getWin().focus();
398                         inst.selection.moveToBookmark(inst.spellCheckerBookmark);
399                 }
400
401                 // Ignore suggestions for other ajax responses
402                 if (cmd == "suggest" && id != inst.editorId + "|" + self._counter)
403                         return;
404
405                 if (!el) {
406                         text = '' + text;
407
408                         if (text.length > 500)
409                                 text = text.substring(500);
410
411                         inst.spellcheckerOn = false;
412                         tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton');
413                         alert("Could not execute AJAX call, server didn't return valid a XML.\nResponse: " + text);
414                         return;
415                 }
416
417                 err = el.getAttribute("error");
418
419                 if (err == "true") {
420                         inst.spellcheckerOn = false;
421                         tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton');
422                         alert(el.getAttribute("msg"));
423                         return;
424                 }
425
426                 switch (cmd) {
427                         case "spell":
428                                 if (xml.documentElement.firstChild) {
429                                         self._markWords(inst.getDoc(), inst.getBody(), decodeURIComponent(el.firstChild.nodeValue).split('+'));
430                                         inst.selection.moveToBookmark(inst.spellCheckerBookmark);
431
432                                         if(tinyMCE.getParam('spellchecker_report_misspellings', false))
433                                                 alert(tinyMCE.getLang('lang_spellchecker_mpell_found', '', true, {words : self._countWords(inst)}));
434                                 } else
435                                         alert(tinyMCE.getLang('lang_spellchecker_no_mpell', '', true));
436
437                                 self._checkDone(inst);
438
439                                 // Odd stuff FF removed useCSS, disable state for it
440                                 inst.useCSS = false;
441
442                                 break;
443
444                         case "suggest":
445                                 self._buildMenu(el.firstChild ? decodeURIComponent(el.firstChild.nodeValue).split('+') : null, 10);
446                                 self._contextMenu.show();
447                                 break;
448                 }
449         },
450
451         _getWordSeparators : function() {
452                 var i, re = '', ch = tinyMCE.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c');
453
454                 for (i=0; i<ch.length; i++)
455                         re += '\\' + ch.charAt(i);
456
457                 return re;
458         },
459
460         _getWordList : function(n) {
461                 var i, x, s, nv = '', nl = tinyMCE.getNodeTree(n, [], 3), wl = [];
462                 var re = TinyMCE_SpellCheckerPlugin._getWordSeparators();
463
464                 for (i=0; i<nl.length; i++) {
465                         if (!new RegExp('/SCRIPT|STYLE/').test(nl[i].parentNode.nodeName))
466                                 nv += nl[i].nodeValue + " ";
467                 }
468
469                 nv = nv.replace(new RegExp('([0-9]|[' + re + '])', 'g'), ' ');
470                 nv = tinyMCE.trim(nv.replace(/(\s+)/g, ' '));
471
472                 nl = nv.split(/\s+/);
473                 for (i=0; i<nl.length; i++) {
474                         s = false;
475                         for (x=0; x<wl.length; x++) {
476                                 if (wl[x] == nl[i]) {
477                                         s = true;
478                                         break;
479                                 }
480                         }
481
482                         if (!s && nl[i].length > 0)
483                                 wl[wl.length] = nl[i];
484                 }
485
486                 return wl.join(' ');
487         },
488
489         _removeWords : function(doc, word, cleanup) {
490                 var i, c, nl = doc.getElementsByTagName("span");
491                 var self = TinyMCE_SpellCheckerPlugin;
492                 var inst = tinyMCE.selectedInstance, b = inst ? inst.selection.getBookmark() : null;
493
494                 word = typeof(word) == 'undefined' ? null : word;
495
496                 for (i=nl.length-1; i>=0; i--) {
497                         c = tinyMCE.getAttrib(nl[i], 'class');
498
499                         if ((c == 'mceItemHiddenSpellWord' || c == 'mceItemHidden') && (word == null || nl[i].innerHTML == word))
500                                 self._removeWord(nl[i]);
501                 }
502
503                 if (b && !cleanup)
504                         inst.selection.moveToBookmark(b);
505         },
506
507         _checkDone : function(inst) {
508                 var self = TinyMCE_SpellCheckerPlugin;
509                 var w = self._countWords(inst);
510
511                 if (w == 0) {
512                         self._removeWords(inst.getDoc());
513                         inst.spellcheckerOn = false;
514                         tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton');
515                 }
516         },
517
518         _countWords : function(inst) {
519                 var i, w = 0, nl = inst.getDoc().getElementsByTagName("span"), c;
520                 var self = TinyMCE_SpellCheckerPlugin;
521
522                 for (i=nl.length-1; i>=0; i--) {
523                         c = tinyMCE.getAttrib(nl[i], 'class');
524
525                         if (c == 'mceItemHiddenSpellWord')
526                                 w++;
527                 }
528
529                 return w;
530         },
531
532         _removeWord : function(e) {
533                 if (e != null)
534                         tinyMCE.setOuterHTML(e, e.innerHTML);
535         },
536
537         _markWords : function(doc, n, wl) {
538                 var i, nv, nn, nl = tinyMCE.getNodeTree(n, new Array(), 3);
539                 var r1, r2, r3, r4, r5, w = '';
540                 var re = TinyMCE_SpellCheckerPlugin._getWordSeparators();
541
542                 for (i=0; i<wl.length; i++) {
543                         if (wl[i].length > 0)
544                                 w += wl[i] + ((i == wl.length-1) ? '' : '|');
545                 }
546
547                 for (i=0; i<nl.length; i++) {
548                         nv = nl[i].nodeValue;
549
550                         r1 = new RegExp('([' + re + '])(' + w + ')([' + re + '])', 'g');
551                         r2 = new RegExp('^(' + w + ')', 'g');
552                         r3 = new RegExp('(' + w + ')([' + re + ']?)$', 'g');
553                         r4 = new RegExp('^(' + w + ')([' + re + ']?)$', 'g');
554                         r5 = new RegExp('(' + w + ')([' + re + '])', 'g');
555
556                         if (r1.test(nv) || r2.test(nv) || r3.test(nv) || r4.test(nv)) {
557                                 nv = tinyMCE.xmlEncode(nv).replace('&#39;', "'");
558                                 nv = nv.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2');
559                                 nv = nv.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2');
560
561                                 nn = doc.createElement('span');
562                                 nn.className = "mceItemHidden";
563                                 nn.innerHTML = nv;
564
565                                 // Remove old text node
566                                 nl[i].parentNode.replaceChild(nn, nl[i]);
567                         }
568                 }
569         },
570
571         _buildMenu : function(sg, max) {
572                 var i, self = TinyMCE_SpellCheckerPlugin, cm = self._contextMenu;
573
574                 cm.clear();
575
576                 if (sg != null) {
577                         cm.addTitle(tinyMCE.getLang('lang_spellchecker_sug', '', true));
578
579                         for (i=0; i<sg.length && i<max; i++)
580                                 cm.addItem(sg[i], 'tinyMCE.execCommand("mceSpellCheckReplace",false,"' + sg[i] + '");');
581
582                         cm.addSeparator();
583                 } else
584                         cm.addTitle(tinyMCE.getLang('lang_spellchecker_no_sug', '', true));
585
586                 cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_word', '', true), 'tinyMCE.execCommand(\'mceSpellCheckIgnore\');');
587                 cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_words', '', true), 'tinyMCE.execCommand(\'mceSpellCheckIgnoreAll\');');
588
589                 cm.update();
590         },
591
592         _getAjaxHTTP : function() {
593                 try {
594                         return new ActiveXObject('Msxml2.XMLHTTP')
595                 } catch (e) {
596                         try {
597                                 return new ActiveXObject('Microsoft.XMLHTTP')
598                         } catch (e) {
599                                 return new XMLHttpRequest();
600                         }
601                 }
602         },
603
604         /**
605          * Perform AJAX call.
606          *
607          * @param {string} u URL of AJAX service.
608          * @param {function} f Function to call when response arrives.
609          * @param {string} m Request method post or get.
610          * @param {Array} a Array with arguments to send.
611          */
612         _sendAjax : function(u, f, m, a) {
613                 var x = TinyMCE_SpellCheckerPlugin._getAjaxHTTP();
614
615                 x.open(m, u, true);
616
617                 x.onreadystatechange = function() {
618                         if (x.readyState == 4)
619                                 f(x.responseXML, x.responseText);
620                 };
621
622                 if (m == 'post')
623                         x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
624
625                 x.send(a);
626         }
627 };
628
629 // Register plugin
630 tinyMCE.addPlugin('spellchecker', TinyMCE_SpellCheckerPlugin);