Mercurial > public > sg101
view static/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js @ 645:99f7917702ca
Fix 081a88b3bfc8, javascript resize of forum images.
Commit 081a88b3bfc8 broke those pages that loaded forums.js but did not load
the imagesLoaded jQuery extension. Now we have arranged it so that only the
forums topic view loads imagesLoaded and put the resizing javascript inline.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Mon, 11 Mar 2013 15:30:25 -0500 |
parents | 6c182ceb7147 |
children |
line wrap: on
line source
/** * editor_plugin_src.js * * Copyright 2009, Moxiecode Systems AB * Released under LGPL License. * * License: http://tinymce.moxiecode.com/license * Contributing: http://tinymce.moxiecode.com/contributing */ (function() { var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM; tinymce.create('tinymce.plugins.SpellcheckerPlugin', { getInfo : function() { return { longname : 'Spellchecker', author : 'Moxiecode Systems AB', authorurl : 'http://tinymce.moxiecode.com', infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker', version : tinymce.majorVersion + "." + tinymce.minorVersion }; }, init : function(ed, url) { var t = this, cm; t.url = url; t.editor = ed; t.rpcUrl = ed.getParam("spellchecker_rpc_url", "{backend}"); if (t.rpcUrl == '{backend}') { // Sniff if the browser supports native spellchecking (Don't know of a better way) if (tinymce.isIE) return; t.hasSupport = true; // Disable the context menu when spellchecking is active ed.onContextMenu.addToTop(function(ed, e) { if (t.active) return false; }); } // Register commands ed.addCommand('mceSpellCheck', function() { if (t.rpcUrl == '{backend}') { // Enable/disable native spellchecker t.editor.getBody().spellcheck = t.active = !t.active; return; } if (!t.active) { ed.setProgressState(1); t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) { if (r.length > 0) { t.active = 1; t._markWords(r); ed.setProgressState(0); ed.nodeChanged(); } else { ed.setProgressState(0); if (ed.getParam('spellchecker_report_no_misspellings', true)) ed.windowManager.alert('spellchecker.no_mpell'); } }); } else t._done(); }); if (ed.settings.content_css !== false) ed.contentCSS.push(url + '/css/content.css'); ed.onClick.add(t._showMenu, t); ed.onContextMenu.add(t._showMenu, t); ed.onBeforeGetContent.add(function() { if (t.active) t._removeWords(); }); ed.onNodeChange.add(function(ed, cm) { cm.setActive('spellchecker', t.active); }); ed.onSetContent.add(function() { t._done(); }); ed.onBeforeGetContent.add(function() { t._done(); }); ed.onBeforeExecCommand.add(function(ed, cmd) { if (cmd == 'mceFullScreen') t._done(); }); // Find selected language t.languages = {}; 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) { if (k.indexOf('+') === 0) { k = k.substring(1); t.selectedLang = v; } t.languages[k] = v; }); }, createControl : function(n, cm) { var t = this, c, ed = t.editor; if (n == 'spellchecker') { // Use basic button if we use the native spellchecker if (t.rpcUrl == '{backend}') { // Create simple toggle button if we have native support if (t.hasSupport) c = cm.createButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); return c; } c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); c.onRenderMenu.add(function(c, m) { m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1); each(t.languages, function(v, k) { var o = {icon : 1}, mi; o.onclick = function() { if (v == t.selectedLang) { return; } mi.setSelected(1); t.selectedItem.setSelected(0); t.selectedItem = mi; t.selectedLang = v; }; o.title = k; mi = m.add(o); mi.setSelected(v == t.selectedLang); if (v == t.selectedLang) t.selectedItem = mi; }) }); return c; } }, // Internal functions _walk : function(n, f) { var d = this.editor.getDoc(), w; if (d.createTreeWalker) { w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); while ((n = w.nextNode()) != null) f.call(this, n); } else tinymce.walk(n, f, 'childNodes'); }, _getSeparators : function() { var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c'); // Build word separator regexp for (i=0; i<str.length; i++) re += '\\' + str.charAt(i); return re; }, _getWords : function() { var ed = this.editor, wl = [], tx = '', lo = {}, rawWords = []; // Get area text this._walk(ed.getBody(), function(n) { if (n.nodeType == 3) tx += n.nodeValue + ' '; }); // split the text up into individual words if (ed.getParam('spellchecker_word_pattern')) { // look for words that match the pattern rawWords = tx.match('(' + ed.getParam('spellchecker_word_pattern') + ')', 'gi'); } else { // Split words by separator tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' '); tx = tinymce.trim(tx.replace(/(\s+)/g, ' ')); rawWords = tx.split(' '); } // Build word array and remove duplicates each(rawWords, function(v) { if (!lo[v]) { wl.push(v); lo[v] = 1; } }); return wl; }, _removeWords : function(w) { var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark(); each(dom.select('span').reverse(), function(n) { if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) { if (!w || dom.decode(n.innerHTML) == w) dom.remove(n, 1); } }); se.moveToBookmark(b); }, _markWords : function(wl) { var ed = this.editor, dom = ed.dom, doc = ed.getDoc(), se = ed.selection, b = se.getBookmark(), nl = [], w = wl.join('|'), re = this._getSeparators(), rx = new RegExp('(^|[' + re + '])(' + w + ')(?=[' + re + ']|$)', 'g'); // Collect all text nodes this._walk(ed.getBody(), function(n) { if (n.nodeType == 3) { nl.push(n); } }); // Wrap incorrect words in spans each(nl, function(n) { var node, elem, txt, pos, v = n.nodeValue; if (rx.test(v)) { // Encode the content v = dom.encode(v); // Create container element elem = dom.create('span', {'class' : 'mceItemHidden'}); // Following code fixes IE issues by creating text nodes // using DOM methods instead of innerHTML. // Bug #3124: <PRE> elements content is broken after spellchecking. // Bug #1408: Preceding whitespace characters are removed // @TODO: I'm not sure that both are still issues on IE9. if (tinymce.isIE) { // Enclose mispelled words with temporal tag v = v.replace(rx, '$1<mcespell>$2</mcespell>'); // Loop over the content finding mispelled words while ((pos = v.indexOf('<mcespell>')) != -1) { // Add text node for the content before the word txt = v.substring(0, pos); if (txt.length) { node = doc.createTextNode(dom.decode(txt)); elem.appendChild(node); } v = v.substring(pos+10); pos = v.indexOf('</mcespell>'); txt = v.substring(0, pos); v = v.substring(pos+11); // Add span element for the word elem.appendChild(dom.create('span', {'class' : 'mceItemHiddenSpellWord'}, txt)); } // Add text node for the rest of the content if (v.length) { node = doc.createTextNode(dom.decode(v)); elem.appendChild(node); } } else { // Other browsers preserve whitespace characters on innerHTML usage elem.innerHTML = v.replace(rx, '$1<span class="mceItemHiddenSpellWord">$2</span>'); } // Finally, replace the node with the container dom.replace(elem, n); } }); se.moveToBookmark(b); }, _showMenu : function(ed, e) { var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin()), wordSpan = e.target; e = 0; // Fixes IE memory leak if (!m) { m = ed.controlManager.createDropMenu('spellcheckermenu', {'class' : 'mceNoIcons'}); t._menu = m; } if (dom.hasClass(wordSpan, 'mceItemHiddenSpellWord')) { m.removeAll(); m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1); t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(wordSpan.innerHTML)], function(r) { var ignoreRpc; m.removeAll(); if (r.length > 0) { m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); each(r, function(v) { m.add({title : v, onclick : function() { dom.replace(ed.getDoc().createTextNode(v), wordSpan); t._checkDone(); }}); }); m.addSeparator(); } else m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); ignoreRpc = t.editor.getParam("spellchecker_enable_ignore_rpc", ''); m.add({ title : 'spellchecker.ignore_word', onclick : function() { var word = wordSpan.innerHTML; dom.remove(wordSpan, 1); t._checkDone(); // tell the server if we need to if (ignoreRpc) { ed.setProgressState(1); t._sendRPC('ignoreWord', [t.selectedLang, word], function(r) { ed.setProgressState(0); }); } } }); m.add({ title : 'spellchecker.ignore_words', onclick : function() { var word = wordSpan.innerHTML; t._removeWords(dom.decode(word)); t._checkDone(); // tell the server if we need to if (ignoreRpc) { ed.setProgressState(1); t._sendRPC('ignoreWords', [t.selectedLang, word], function(r) { ed.setProgressState(0); }); } } }); if (t.editor.getParam("spellchecker_enable_learn_rpc")) { m.add({ title : 'spellchecker.learn_word', onclick : function() { var word = wordSpan.innerHTML; dom.remove(wordSpan, 1); t._checkDone(); ed.setProgressState(1); t._sendRPC('learnWord', [t.selectedLang, word], function(r) { ed.setProgressState(0); }); } }); } m.update(); }); p1 = dom.getPos(ed.getContentAreaContainer()); m.settings.offset_x = p1.x; m.settings.offset_y = p1.y; ed.selection.select(wordSpan); p1 = dom.getPos(wordSpan); m.showMenu(p1.x, p1.y + wordSpan.offsetHeight - vp.y); return tinymce.dom.Event.cancel(e); } else m.hideMenu(); }, _checkDone : function() { var t = this, ed = t.editor, dom = ed.dom, o; each(dom.select('span'), function(n) { if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) { o = true; return false; } }); if (!o) t._done(); }, _done : function() { var t = this, la = t.active; if (t.active) { t.active = 0; t._removeWords(); if (t._menu) t._menu.hideMenu(); if (la) t.editor.nodeChanged(); } }, _sendRPC : function(m, p, cb) { var t = this; JSONRequest.sendRPC({ url : t.rpcUrl, method : m, params : p, success : cb, error : function(e, x) { t.editor.setProgressState(0); t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText)); } }); } }); // Register plugin tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin); })();