annotate media/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js @ 133:c515b7401078

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