GMaps related JS changed to use new google namespace.
Google is going to change permanently in the future the way to
load its services, so better stay safe.
Also this commit shows uses of the new melange.js module.
Fixes Issue 634.
/**
* $Id: editor_plugin_src.js 425 2007-11-21 15:17:39Z spocke $
*
* @author Moxiecode
* @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(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;
// Register commands
ed.addCommand('mceSpellCheck', function() {
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);
ed.windowManager.alert('spellchecker.no_mpell');
}
});
} else
t._done();
});
ed.onInit.add(function() {
if (ed.settings.content_css !== false)
ed.dom.loadCSS(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') {
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() {
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 = {};
// Get area text
this._walk(ed.getBody(), function(n) {
if (n.nodeType == 3)
tx += n.nodeValue + ' ';
});
// Split words by separator
tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' ');
tx = tinymce.trim(tx.replace(/(\s+)/g, ' '));
// Build word array and remove duplicates
each(tx.split(' '), 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 r1, r2, r3, r4, r5, w = '', ed = this.editor, re = this._getSeparators(), dom = ed.dom, nl = [];
var se = ed.selection, b = se.getBookmark();
each(wl, function(v) {
w += (w ? '|' : '') + v;
});
r1 = new RegExp('([' + re + '])(' + w + ')([' + re + '])', 'g');
r2 = new RegExp('^(' + w + ')', 'g');
r3 = new RegExp('(' + w + ')([' + re + ']?)$', 'g');
r4 = new RegExp('^(' + w + ')([' + re + ']?)$', 'g');
r5 = new RegExp('(' + w + ')([' + re + '])', 'g');
// Collect all text nodes
this._walk(this.editor.getBody(), function(n) {
if (n.nodeType == 3) {
nl.push(n);
}
});
// Wrap incorrect words in spans
each(nl, function(n) {
var v;
if (n.nodeType == 3) {
v = n.nodeValue;
if (r1.test(v) || r2.test(v) || r3.test(v) || r4.test(v)) {
v = dom.encode(v);
v = v.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2');
v = v.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2');
dom.replace(dom.create('span', {'class' : 'mceItemHidden'}, v), 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());
if (!m) {
p1 = DOM.getPos(ed.getContentAreaContainer());
//p2 = DOM.getPos(ed.getContainer());
m = ed.controlManager.createDropMenu('spellcheckermenu', {
offset_x : p1.x,
offset_y : p1.y,
'class' : 'mceNoIcons'
});
t._menu = m;
}
if (dom.hasClass(e.target, 'mceItemHiddenSpellWord')) {
m.removeAll();
m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(e.target.innerHTML)], function(r) {
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), e.target);
t._checkDone();
}});
});
m.addSeparator();
} else
m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
m.add({
title : 'spellchecker.ignore_word',
onclick : function() {
dom.remove(e.target, 1);
t._checkDone();
}
});
m.add({
title : 'spellchecker.ignore_words',
onclick : function() {
t._removeWords(dom.decode(e.target.innerHTML));
t._checkDone();
}
});
m.update();
});
ed.selection.select(e.target);
p1 = dom.getPos(e.target);
m.showMenu(p1.x, p1.y + e.target.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, url = t.editor.getParam("spellchecker_rpc_url", "{backend}");
if (url == '{backend}') {
t.editor.setProgressState(0);
alert('Please specify: spellchecker_rpc_url');
return;
}
JSONRequest.sendRPC({
url : url,
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);
})();