raw
mp-wp_genesis           1 /**
mp-wp_genesis 2 * $Id: editor_plugin_src.js 425 2007-11-21 15:17:39Z spocke $
mp-wp_genesis 3 *
mp-wp_genesis 4 * @author Moxiecode
mp-wp_genesis 5 */
mp-wp_genesis 6
mp-wp_genesis 7 (function() {
mp-wp_genesis 8 var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM;
mp-wp_genesis 9
mp-wp_genesis 10 tinymce.create('tinymce.plugins.SpellcheckerPlugin', {
mp-wp_genesis 11 getInfo : function() {
mp-wp_genesis 12 return {
mp-wp_genesis 13 longname : 'Spellchecker',
mp-wp_genesis 14 author : 'Moxiecode Systems AB',
mp-wp_genesis 15 authorurl : 'http://tinymce.moxiecode.com',
mp-wp_genesis 16 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker',
mp-wp_genesis 17 version : "2.0.2"
mp-wp_genesis 18 };
mp-wp_genesis 19 },
mp-wp_genesis 20
mp-wp_genesis 21 init : function(ed, url) {
mp-wp_genesis 22 var t = this, cm;
mp-wp_genesis 23
mp-wp_genesis 24 t.url = url;
mp-wp_genesis 25 t.editor = ed;
mp-wp_genesis 26
mp-wp_genesis 27 // Register commands
mp-wp_genesis 28 ed.addCommand('mceSpellCheck', function() {
mp-wp_genesis 29 if (!t.active) {
mp-wp_genesis 30 ed.setProgressState(1);
mp-wp_genesis 31 t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) {
mp-wp_genesis 32 if (r.length > 0) {
mp-wp_genesis 33 t.active = 1;
mp-wp_genesis 34 t._markWords(r);
mp-wp_genesis 35 ed.setProgressState(0);
mp-wp_genesis 36 ed.nodeChanged();
mp-wp_genesis 37 } else {
mp-wp_genesis 38 ed.setProgressState(0);
mp-wp_genesis 39 ed.windowManager.alert('spellchecker.no_mpell');
mp-wp_genesis 40 }
mp-wp_genesis 41 });
mp-wp_genesis 42 } else
mp-wp_genesis 43 t._done();
mp-wp_genesis 44 });
mp-wp_genesis 45
mp-wp_genesis 46 ed.onInit.add(function() {
mp-wp_genesis 47 if (ed.settings.content_css !== false)
mp-wp_genesis 48 ed.dom.loadCSS(url + '/css/content.css');
mp-wp_genesis 49 });
mp-wp_genesis 50
mp-wp_genesis 51 ed.onClick.add(t._showMenu, t);
mp-wp_genesis 52 ed.onContextMenu.add(t._showMenu, t);
mp-wp_genesis 53 ed.onBeforeGetContent.add(function() {
mp-wp_genesis 54 if (t.active)
mp-wp_genesis 55 t._removeWords();
mp-wp_genesis 56 });
mp-wp_genesis 57
mp-wp_genesis 58 ed.onNodeChange.add(function(ed, cm) {
mp-wp_genesis 59 cm.setActive('spellchecker', t.active);
mp-wp_genesis 60 });
mp-wp_genesis 61
mp-wp_genesis 62 ed.onSetContent.add(function() {
mp-wp_genesis 63 t._done();
mp-wp_genesis 64 });
mp-wp_genesis 65
mp-wp_genesis 66 ed.onBeforeGetContent.add(function() {
mp-wp_genesis 67 t._done();
mp-wp_genesis 68 });
mp-wp_genesis 69
mp-wp_genesis 70 ed.onBeforeExecCommand.add(function(ed, cmd) {
mp-wp_genesis 71 if (cmd == 'mceFullScreen')
mp-wp_genesis 72 t._done();
mp-wp_genesis 73 });
mp-wp_genesis 74
mp-wp_genesis 75 // Find selected language
mp-wp_genesis 76 t.languages = {};
mp-wp_genesis 77 each(ed.getParam('spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv', 'hash'), function(v, k) {
mp-wp_genesis 78 if (k.indexOf('+') === 0) {
mp-wp_genesis 79 k = k.substring(1);
mp-wp_genesis 80 t.selectedLang = v;
mp-wp_genesis 81 }
mp-wp_genesis 82
mp-wp_genesis 83 t.languages[k] = v;
mp-wp_genesis 84 });
mp-wp_genesis 85 },
mp-wp_genesis 86
mp-wp_genesis 87 createControl : function(n, cm) {
mp-wp_genesis 88 var t = this, c, ed = t.editor;
mp-wp_genesis 89
mp-wp_genesis 90 if (n == 'spellchecker') {
mp-wp_genesis 91 c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t});
mp-wp_genesis 92
mp-wp_genesis 93 c.onRenderMenu.add(function(c, m) {
mp-wp_genesis 94 m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
mp-wp_genesis 95 each(t.languages, function(v, k) {
mp-wp_genesis 96 var o = {icon : 1}, mi;
mp-wp_genesis 97
mp-wp_genesis 98 o.onclick = function() {
mp-wp_genesis 99 mi.setSelected(1);
mp-wp_genesis 100 t.selectedItem.setSelected(0);
mp-wp_genesis 101 t.selectedItem = mi;
mp-wp_genesis 102 t.selectedLang = v;
mp-wp_genesis 103 };
mp-wp_genesis 104
mp-wp_genesis 105 o.title = k;
mp-wp_genesis 106 mi = m.add(o);
mp-wp_genesis 107 mi.setSelected(v == t.selectedLang);
mp-wp_genesis 108
mp-wp_genesis 109 if (v == t.selectedLang)
mp-wp_genesis 110 t.selectedItem = mi;
mp-wp_genesis 111 })
mp-wp_genesis 112 });
mp-wp_genesis 113
mp-wp_genesis 114 return c;
mp-wp_genesis 115 }
mp-wp_genesis 116 },
mp-wp_genesis 117
mp-wp_genesis 118 // Internal functions
mp-wp_genesis 119
mp-wp_genesis 120 _walk : function(n, f) {
mp-wp_genesis 121 var d = this.editor.getDoc(), w;
mp-wp_genesis 122
mp-wp_genesis 123 if (d.createTreeWalker) {
mp-wp_genesis 124 w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
mp-wp_genesis 125
mp-wp_genesis 126 while ((n = w.nextNode()) != null)
mp-wp_genesis 127 f.call(this, n);
mp-wp_genesis 128 } else
mp-wp_genesis 129 tinymce.walk(n, f, 'childNodes');
mp-wp_genesis 130 },
mp-wp_genesis 131
mp-wp_genesis 132 _getSeparators : function() {
mp-wp_genesis 133 var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}');
mp-wp_genesis 134
mp-wp_genesis 135 // Build word separator regexp
mp-wp_genesis 136 for (i=0; i<str.length; i++)
mp-wp_genesis 137 re += '\\' + str.charAt(i);
mp-wp_genesis 138
mp-wp_genesis 139 return re;
mp-wp_genesis 140 },
mp-wp_genesis 141
mp-wp_genesis 142 _getWords : function() {
mp-wp_genesis 143 var ed = this.editor, wl = [], tx = '', lo = {};
mp-wp_genesis 144
mp-wp_genesis 145 // Get area text
mp-wp_genesis 146 this._walk(ed.getBody(), function(n) {
mp-wp_genesis 147 if (n.nodeType == 3)
mp-wp_genesis 148 tx += n.nodeValue + ' ';
mp-wp_genesis 149 });
mp-wp_genesis 150
mp-wp_genesis 151 // Split words by separator
mp-wp_genesis 152 tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' ');
mp-wp_genesis 153 tx = tinymce.trim(tx.replace(/(\s+)/g, ' '));
mp-wp_genesis 154
mp-wp_genesis 155 // Build word array and remove duplicates
mp-wp_genesis 156 each(tx.split(' '), function(v) {
mp-wp_genesis 157 if (!lo[v]) {
mp-wp_genesis 158 wl.push(v);
mp-wp_genesis 159 lo[v] = 1;
mp-wp_genesis 160 }
mp-wp_genesis 161 });
mp-wp_genesis 162
mp-wp_genesis 163 return wl;
mp-wp_genesis 164 },
mp-wp_genesis 165
mp-wp_genesis 166 _removeWords : function(w) {
mp-wp_genesis 167 var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark();
mp-wp_genesis 168
mp-wp_genesis 169 each(dom.select('span').reverse(), function(n) {
mp-wp_genesis 170 if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) {
mp-wp_genesis 171 if (!w || dom.decode(n.innerHTML) == w)
mp-wp_genesis 172 dom.remove(n, 1);
mp-wp_genesis 173 }
mp-wp_genesis 174 });
mp-wp_genesis 175
mp-wp_genesis 176 se.moveToBookmark(b);
mp-wp_genesis 177 },
mp-wp_genesis 178
mp-wp_genesis 179 _markWords : function(wl) {
mp-wp_genesis 180 var r1, r2, r3, r4, r5, w = '', ed = this.editor, re = this._getSeparators(), dom = ed.dom, nl = [];
mp-wp_genesis 181 var se = ed.selection, b = se.getBookmark();
mp-wp_genesis 182
mp-wp_genesis 183 each(wl, function(v) {
mp-wp_genesis 184 w += (w ? '|' : '') + v;
mp-wp_genesis 185 });
mp-wp_genesis 186
mp-wp_genesis 187 r1 = new RegExp('([' + re + '])(' + w + ')([' + re + '])', 'g');
mp-wp_genesis 188 r2 = new RegExp('^(' + w + ')', 'g');
mp-wp_genesis 189 r3 = new RegExp('(' + w + ')([' + re + ']?)$', 'g');
mp-wp_genesis 190 r4 = new RegExp('^(' + w + ')([' + re + ']?)$', 'g');
mp-wp_genesis 191 r5 = new RegExp('(' + w + ')([' + re + '])', 'g');
mp-wp_genesis 192
mp-wp_genesis 193 // Collect all text nodes
mp-wp_genesis 194 this._walk(this.editor.getBody(), function(n) {
mp-wp_genesis 195 if (n.nodeType == 3) {
mp-wp_genesis 196 nl.push(n);
mp-wp_genesis 197 }
mp-wp_genesis 198 });
mp-wp_genesis 199
mp-wp_genesis 200 // Wrap incorrect words in spans
mp-wp_genesis 201 each(nl, function(n) {
mp-wp_genesis 202 var v;
mp-wp_genesis 203
mp-wp_genesis 204 if (n.nodeType == 3) {
mp-wp_genesis 205 v = n.nodeValue;
mp-wp_genesis 206
mp-wp_genesis 207 if (r1.test(v) || r2.test(v) || r3.test(v) || r4.test(v)) {
mp-wp_genesis 208 v = dom.encode(v);
mp-wp_genesis 209 v = v.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2');
mp-wp_genesis 210 v = v.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2');
mp-wp_genesis 211
mp-wp_genesis 212 dom.replace(dom.create('span', {'class' : 'mceItemHidden'}, v), n);
mp-wp_genesis 213 }
mp-wp_genesis 214 }
mp-wp_genesis 215 });
mp-wp_genesis 216
mp-wp_genesis 217 se.moveToBookmark(b);
mp-wp_genesis 218 },
mp-wp_genesis 219
mp-wp_genesis 220 _showMenu : function(ed, e) {
mp-wp_genesis 221 var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin());
mp-wp_genesis 222
mp-wp_genesis 223 if (!m) {
mp-wp_genesis 224 p1 = DOM.getPos(ed.getContentAreaContainer());
mp-wp_genesis 225 //p2 = DOM.getPos(ed.getContainer());
mp-wp_genesis 226
mp-wp_genesis 227 m = ed.controlManager.createDropMenu('spellcheckermenu', {
mp-wp_genesis 228 offset_x : p1.x,
mp-wp_genesis 229 offset_y : p1.y,
mp-wp_genesis 230 'class' : 'mceNoIcons'
mp-wp_genesis 231 });
mp-wp_genesis 232
mp-wp_genesis 233 t._menu = m;
mp-wp_genesis 234 }
mp-wp_genesis 235
mp-wp_genesis 236 if (dom.hasClass(e.target, 'mceItemHiddenSpellWord')) {
mp-wp_genesis 237 m.removeAll();
mp-wp_genesis 238 m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
mp-wp_genesis 239
mp-wp_genesis 240 t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(e.target.innerHTML)], function(r) {
mp-wp_genesis 241 m.removeAll();
mp-wp_genesis 242
mp-wp_genesis 243 if (r.length > 0) {
mp-wp_genesis 244 m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
mp-wp_genesis 245 each(r, function(v) {
mp-wp_genesis 246 m.add({title : v, onclick : function() {
mp-wp_genesis 247 dom.replace(ed.getDoc().createTextNode(v), e.target);
mp-wp_genesis 248 t._checkDone();
mp-wp_genesis 249 }});
mp-wp_genesis 250 });
mp-wp_genesis 251
mp-wp_genesis 252 m.addSeparator();
mp-wp_genesis 253 } else
mp-wp_genesis 254 m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
mp-wp_genesis 255
mp-wp_genesis 256 m.add({
mp-wp_genesis 257 title : 'spellchecker.ignore_word',
mp-wp_genesis 258 onclick : function() {
mp-wp_genesis 259 dom.remove(e.target, 1);
mp-wp_genesis 260 t._checkDone();
mp-wp_genesis 261 }
mp-wp_genesis 262 });
mp-wp_genesis 263
mp-wp_genesis 264 m.add({
mp-wp_genesis 265 title : 'spellchecker.ignore_words',
mp-wp_genesis 266 onclick : function() {
mp-wp_genesis 267 t._removeWords(dom.decode(e.target.innerHTML));
mp-wp_genesis 268 t._checkDone();
mp-wp_genesis 269 }
mp-wp_genesis 270 });
mp-wp_genesis 271
mp-wp_genesis 272 m.update();
mp-wp_genesis 273 });
mp-wp_genesis 274
mp-wp_genesis 275 ed.selection.select(e.target);
mp-wp_genesis 276 p1 = dom.getPos(e.target);
mp-wp_genesis 277 m.showMenu(p1.x, p1.y + e.target.offsetHeight - vp.y);
mp-wp_genesis 278
mp-wp_genesis 279 return tinymce.dom.Event.cancel(e);
mp-wp_genesis 280 } else
mp-wp_genesis 281 m.hideMenu();
mp-wp_genesis 282 },
mp-wp_genesis 283
mp-wp_genesis 284 _checkDone : function() {
mp-wp_genesis 285 var t = this, ed = t.editor, dom = ed.dom, o;
mp-wp_genesis 286
mp-wp_genesis 287 each(dom.select('span'), function(n) {
mp-wp_genesis 288 if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) {
mp-wp_genesis 289 o = true;
mp-wp_genesis 290 return false;
mp-wp_genesis 291 }
mp-wp_genesis 292 });
mp-wp_genesis 293
mp-wp_genesis 294 if (!o)
mp-wp_genesis 295 t._done();
mp-wp_genesis 296 },
mp-wp_genesis 297
mp-wp_genesis 298 _done : function() {
mp-wp_genesis 299 var t = this, la = t.active;
mp-wp_genesis 300
mp-wp_genesis 301 if (t.active) {
mp-wp_genesis 302 t.active = 0;
mp-wp_genesis 303 t._removeWords();
mp-wp_genesis 304
mp-wp_genesis 305 if (t._menu)
mp-wp_genesis 306 t._menu.hideMenu();
mp-wp_genesis 307
mp-wp_genesis 308 if (la)
mp-wp_genesis 309 t.editor.nodeChanged();
mp-wp_genesis 310 }
mp-wp_genesis 311 },
mp-wp_genesis 312
mp-wp_genesis 313 _sendRPC : function(m, p, cb) {
mp-wp_genesis 314 var t = this, url = t.editor.getParam("spellchecker_rpc_url", this.url+'/rpc.php');
mp-wp_genesis 315
mp-wp_genesis 316 if (url == '{backend}') {
mp-wp_genesis 317 t.editor.setProgressState(0);
mp-wp_genesis 318 alert('Please specify: spellchecker_rpc_url');
mp-wp_genesis 319 return;
mp-wp_genesis 320 }
mp-wp_genesis 321
mp-wp_genesis 322 JSONRequest.sendRPC({
mp-wp_genesis 323 url : url,
mp-wp_genesis 324 method : m,
mp-wp_genesis 325 params : p,
mp-wp_genesis 326 success : cb,
mp-wp_genesis 327 error : function(e, x) {
mp-wp_genesis 328 t.editor.setProgressState(0);
mp-wp_genesis 329 t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText));
mp-wp_genesis 330 }
mp-wp_genesis 331 });
mp-wp_genesis 332 }
mp-wp_genesis 333 });
mp-wp_genesis 334
mp-wp_genesis 335 // Register plugin
mp-wp_genesis 336 tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin);
mp-wp_genesis 337 })();