From ed1d212ae2daea5e4bd043417610177093e99f19 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sat, 16 Jan 2016 03:03:51 -0500
Subject: [PATCH] Improved SVG cleanup code

---
 program/js/googiespell.js | 3003 +++++++++++++++-------------------------------------------
 1 files changed, 801 insertions(+), 2,202 deletions(-)

diff --git a/program/js/googiespell.js b/program/js/googiespell.js
index b336b79..bf0eede 100644
--- a/program/js/googiespell.js
+++ b/program/js/googiespell.js
@@ -1,1468 +1,66 @@
-/*
-Last Modified: 29/04/07 18:44:48
+/**
+ * Roundcube SpellCheck script
+ *
+ * jQuery'fied spell checker based on GoogieSpell 4.0
+ * (which was published under GPL "version 2 or any later version")
+ *
+ * @licstart  The following is the entire license notice for the
+ * JavaScript code in this file.
+ *
+ * Copyright (C) 2006 Amir Salihefendic
+ * Copyright (C) 2009 The Roundcube Dev Team
+ * Copyright (C) 2011 Kolab Systems AG
+ *
+ * The JavaScript code in this page is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GNU GPL) as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.  The code is distributed WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+ *
+ * As additional permission under GNU GPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * @licend  The above is the entire license notice
+ * for the JavaScript code in this file.
+ *
+ * @author 4mir Salihefendic <amix@amix.dk> 
+ * @author Aleksander Machniak - <alec [at] alec.pl>
+ */
 
-AJS JavaScript library
-    A very small library with a lot of functionality
-AUTHOR
-    4mir Salihefendic (http://amix.dk) - amix@amix.dk
-LICENSE
-    Copyright (c) 2006 Amir Salihefendic. All rights reserved.
-    Copyright (c) 2005 Bob Ippolito. All rights reserved.
-    http://www.opensource.org/licenses/mit-license.php
-VERSION
-    4.0
-SITE
-    http://orangoo.com/AmiNation/AJS
-**/
-if(!AJS) {
-var AJS = {
-    BASE_URL: "",
+var GOOGIE_CUR_LANG,
+    GOOGIE_DEFAULT_LANG = 'en';
 
-    drag_obj: null,
-    drag_elm: null,
-    _drop_zones: [],
-    _drag_zones: [],
-    _cur_pos: null,
+function GoogieSpell(img_dir, server_url, has_dict)
+{
+    var ref = this,
+        cookie_value = rcmail.get_cookie('language');
 
-    ajaxErrorHandler: null,
+    GOOGIE_CUR_LANG = cookie_value != null ? cookie_value : GOOGIE_DEFAULT_LANG;
 
-////
-// General accessor functions
-////
-    getQueryArgument: function(var_name) {
-        var query = window.location.search.substring(1);
-        var vars = query.split("&");
-        for (var i=0;i<vars.length;i++) {
-            var pair = vars[i].split("=");
-            if (pair[0] == var_name) {
-                return pair[1];
-            }
-        }
-        return null;
-    },
-
-    isIe: function() {
-        return (navigator.userAgent.toLowerCase().indexOf("msie") != -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1);
-    },
-    isNetscape7: function() {
-        return (navigator.userAgent.toLowerCase().indexOf("netscape") != -1 && navigator.userAgent.toLowerCase().indexOf("7.") != -1);
-    },
-    isSafari: function() {
-        return (navigator.userAgent.toLowerCase().indexOf("khtml") != -1);
-    },
-    isOpera: function() {
-        return (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
-    },
-    isMozilla: function() {
-        return (navigator.userAgent.toLowerCase().indexOf("gecko") != -1 && navigator.productSub >= 20030210);
-    },
-    isMac: function() {
-        return (navigator.userAgent.toLowerCase().indexOf('macintosh') != -1);
-    },
-
-
-////
-// Array functions
-////
-    //Shortcut: AJS.$A
-    createArray: function(v) {
-        if(AJS.isArray(v) && !AJS.isString(v))
-            return v;
-        else if(!v)
-            return [];
-        else
-            return [v];
-    },
-
-    forceArray: function(args) {
-        var r = [];
-        AJS.map(args, function(elm) {
-            r.push(elm);
-        });
-        return r;
-    },
-
-    join: function(delim, list) {
-        try {
-            return list.join(delim);
-        }
-        catch(e) {
-            var r = list[0] || '';
-            AJS.map(list, function(elm) {
-                r += delim + elm;
-            }, 1);
-            return r + '';
-        }
-    },
-
-    isIn: function(elm, list) {
-        var i = AJS.getIndex(elm, list);
-        if(i != -1)
-            return true;
-        else
-            return false;
-    },
-
-    getIndex: function(elm, list/*optional*/, eval_fn) {
-        for(var i=0; i < list.length; i++)
-            if(eval_fn && eval_fn(list[i]) || elm == list[i])
-                return i;
-        return -1;
-    },
-
-    getFirst: function(list) {
-        if(list.length > 0)
-            return list[0];
-        else
-            return null;
-    },
-
-    getLast: function(list) {
-        if(list.length > 0)
-            return list[list.length-1];
-        else
-            return null;
-    },
-
-    update: function(l1, l2) {
-        for(var i in l2)
-            l1[i] = l2[i];
-        return l1;
-    },
-
-    flattenList: function(list) {
-        var r = [];
-        var _flatten = function(r, l) {
-            AJS.map(l, function(o) {
-                if(o == null) {}
-                else if (AJS.isArray(o))
-                    _flatten(r, o);
-                else
-                    r.push(o);
-            });
-        }
-        _flatten(r, list);
-        return r;
-    },
-
-
-////
-// Functional programming
-////
-    map: function(list, fn,/*optional*/ start_index, end_index) {
-        var i = 0, l = list.length;
-        if(start_index)
-             i = start_index;
-        if(end_index)
-             l = end_index;
-        for(i; i < l; i++) {
-            var val = fn.apply(null, [list[i], i]);
-            if(val != undefined)
-                return val;
-        }
-    },
-
-    rmap: function(list, fn) {
-        var i = list.length-1, l = 0;
-        for(i; i >= l; i--) {
-            var val = fn.apply(null, [list[i], i]);
-            if(val != undefined)
-                return val;
-        }
-    },
-
-    filter: function(list, fn, /*optional*/ start_index, end_index) {
-        var r = [];
-        AJS.map(list, function(elm) {
-            if(fn(elm))
-                r.push(elm);
-        }, start_index, end_index);
-        return r;
-    },
-
-    partial: function(fn) {
-        var args = AJS.$FA(arguments);
-        args.shift();
-        return function() {
-            args = args.concat(AJS.$FA(arguments));
-            return fn.apply(window, args);
-        }
-    },
-
-
-////
-// DOM functions
-////
-    //Shortcut: AJS.$
-    getElement: function(id) {
-        if(AJS.isString(id) || AJS.isNumber(id))
-            return document.getElementById(id);
-        else
-            return id;
-    },
-
-    //Shortcut: AJS.$$
-    getElements: function(/*id1, id2, id3*/) {
-        var args = AJS.forceArray(arguments);
-        var elements = new Array();
-            for (var i = 0; i < args.length; i++) {
-                var element = AJS.getElement(args[i]);
-                elements.push(element);
-            }
-            return elements;
-    },
-
-    //Shortcut: AJS.$bytc
-    getElementsByTagAndClassName: function(tag_name, class_name, /*optional*/ parent) {
-        var class_elements = [];
-        if(!AJS.isDefined(parent))
-            parent = document;
-        if(!AJS.isDefined(tag_name))
-            tag_name = '*';
-
-        var els = parent.getElementsByTagName(tag_name);
-        var els_len = els.length;
-        var pattern = new RegExp("(^|\\s)" + class_name + "(\\s|$)");
-
-        for (i = 0, j = 0; i < els_len; i++) {
-            if ( pattern.test(els[i].className) || class_name == null ) {
-                class_elements[j] = els[i];
-                j++;
-            }
-        }
-        return class_elements;
-    },
-
-    _nodeWalk: function(elm, tag_name, class_name, fn_next_elm) {
-        var p = fn_next_elm(elm);
-
-        var checkFn;
-        if(tag_name && class_name) {
-            checkFn = function(p) {
-                return AJS.nodeName(p) == tag_name && AJS.hasClass(p, class_name);
-            }
-        }
-        else if(tag_name) {
-            checkFn = function(p) { return AJS.nodeName(p) == tag_name; }
-        }
-        else {
-            checkFn = function(p) { return AJS.hasClass(p, class_name); }
-        }
-
-        while(p) {
-            if(checkFn(p))
-                return p;
-            p = fn_next_elm(p);
-        }
-        return null;
-    },
-
-    getParentBytc: function(elm, tag_name, class_name) {
-        return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.parentNode; });
-    },
-
-    getPreviousSiblingBytc: function(elm, tag_name, class_name) {
-        return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.previousSibling; });
-    },
-
-    getNextSiblingBytc: function(elm, tag_name, class_name) {
-        return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.nextSibling; });
-    },
-
-    //Shortcut: AJS.$f
-    getFormElement: function(form, name) {
-        form = AJS.$(form);
-        var r = null;
-        AJS.map(form.elements, function(elm) {
-            if(elm.name && elm.name == name)
-                r = elm;
-        });
-        return r;
-    },
-
-    formContents: function(form) {
-        var form = AJS.$(form);
-        var r = {};
-        var fn = function(elms) {
-            AJS.map(elms, function(e) {
-                if(e.name)
-                    r[e.name] = e.value || '';
-            });
-        }
-        fn(AJS.$bytc('input', null, form));
-        fn(AJS.$bytc('textarea', null, form));
-        return r;
-    },
-
-    getBody: function() {
-        return AJS.$bytc('body')[0]
-    },
-
-    nodeName: function(elm) {
-        return elm.nodeName.toLowerCase();
-    },
-
-    hasParent: function(elm, parent_to_consider, max_look_up) {
-        if(elm == parent_to_consider)
-            return true;
-        if(max_look_up == 0)
-            return false;
-        return AJS.hasParent(elm.parentNode, parent_to_consider, max_look_up-1);
-    },
-
-    isElementHidden: function(elm) {
-        return ((elm.style.display == "none") || (elm.style.visibility == "hidden"));
-    },
-
-    //Shortcut: AJS.DI
-    documentInsert: function(elm) {
-        if(typeof(elm) == 'string')
-            elm = AJS.HTML2DOM(elm);
-        document.write('<span id="dummy_holder"></span>');
-        AJS.swapDOM(AJS.$('dummy_holder'), elm);
-    },
-
-    cloner: function(element) {
-        return function() {
-            return element.cloneNode(true);
-        }
-    },
-
-    appendToTop: function(elm/*, elms...*/) {
-        var args = AJS.forceArray(arguments).slice(1);
-        if(args.length >= 1) {
-            var first_child = elm.firstChild;
-            if(first_child) {
-                while(true) {
-                    var t_elm = args.shift();
-                    if(t_elm)
-                        AJS.insertBefore(t_elm, first_child);
-                    else
-                        break;
-                }
-            }
-            else {
-                AJS.ACN.apply(null, arguments);
-            }
-        }
-        return elm;
-    },
-
-    //Shortcut: AJS.ACN
-    appendChildNodes: function(elm/*, elms...*/) {
-        if(arguments.length >= 2) {
-            AJS.map(arguments, function(n) {
-                if(AJS.isString(n))
-                    n = AJS.TN(n);
-                if(AJS.isDefined(n))
-                    elm.appendChild(n);
-            }, 1);
-        }
-        return elm;
-    },
-
-    //Shortcut: AJS.RCN
-    replaceChildNodes: function(elm/*, elms...*/) {
-        var child;
-        while ((child = elm.firstChild))
-            elm.removeChild(child);
-        if (arguments.length < 2)
-            return elm;
-        else
-            return AJS.appendChildNodes.apply(null, arguments);
-        return elm;
-    },
-
-    insertAfter: function(elm, reference_elm) {
-        reference_elm.parentNode.insertBefore(elm, reference_elm.nextSibling);
-        return elm;
-    },
-
-    insertBefore: function(elm, reference_elm) {
-        reference_elm.parentNode.insertBefore(elm, reference_elm);
-        return elm;
-    },
-
-    showElement: function(/*elms...*/) {
-        var args = AJS.forceArray(arguments);
-        AJS.map(args, function(elm) { elm.style.display = ''});
-    },
-
-    hideElement: function(elm) {
-        var args = AJS.forceArray(arguments);
-        AJS.map(args, function(elm) { elm.style.display = 'none'});
-    },
-
-    swapDOM: function(dest, src) {
-        dest = AJS.getElement(dest);
-        var parent = dest.parentNode;
-        if (src) {
-            src = AJS.getElement(src);
-            parent.replaceChild(src, dest);
-        } else {
-            parent.removeChild(dest);
-        }
-        return src;
-    },
-
-    removeElement: function(/*elm1, elm2...*/) {
-        var args = AJS.forceArray(arguments);
-        AJS.map(args, function(elm) { AJS.swapDOM(elm, null); });
-    },
-
-    createDOM: function(name, attrs) {
-        var i=0, attr;
-        elm = document.createElement(name);
-
-        if(AJS.isDict(attrs[i])) {
-            for(k in attrs[0]) {
-                attr = attrs[0][k];
-                if(k == "style")
-                    elm.style.cssText = attr;
-                else if(k == "class" || k == 'className')
-                    elm.className = attr;
-                else {
-                    elm.setAttribute(k, attr);
-                }
-            }
-            i++;
-        }
-
-        if(attrs[0] == null)
-            i = 1;
-
-        AJS.map(attrs, function(n) {
-            if(n) {
-                if(AJS.isString(n) || AJS.isNumber(n))
-                    n = AJS.TN(n);
-                elm.appendChild(n);
-            }
-        }, i);
-        return elm;
-    },
-
-    _createDomShortcuts: function() {
-        var elms = [
-                "ul", "li", "td", "tr", "th",
-                "tbody", "table", "input", "span", "b",
-                "a", "div", "img", "button", "h1",
-                "h2", "h3", "br", "textarea", "form",
-                "p", "select", "option", "optgroup", "iframe", "script",
-                "center", "dl", "dt", "dd", "small",
-                "pre"
-        ];
-        var extends_ajs = function(elm) {
-            AJS[elm.toUpperCase()] = function() {
-                return AJS.createDOM.apply(null, [elm, arguments]); 
-            };
-        }
-        AJS.map(elms, extends_ajs);
-        AJS.TN = function(text) { return document.createTextNode(text) };
-    },
-
-    getCssDim: function(dim) {
-        if(AJS.isString(dim))
-            return dim;
-        else
-            return dim + "px";
-    },
-    getCssProperty: function(elm, prop) {
-        elm = AJS.$(elm);
-        var y;
-        if(elm.currentStyle)
-            y = elm.currentStyle[prop];
-	else if (window.getComputedStyle)
-            y = document.defaultView.getComputedStyle(elm,null).getPropertyValue(prop);
-	return y;
-    },
-
-    setStyle: function(/*elm1, elm2..., property, new_value*/) {
-        var args = AJS.forceArray(arguments);
-        var new_val = args.pop();
-        var property = args.pop();
-        AJS.map(args, function(elm) { 
-            elm.style[property] = AJS.getCssDim(new_val);
-        });
-    },
-
-    setWidth: function(/*elm1, elm2..., width*/) {
-        var args = AJS.forceArray(arguments);
-        args.splice(args.length-1, 0, 'width');
-        AJS.setStyle.apply(null, args);
-    },
-    setHeight: function(/*elm1, elm2..., height*/) {
-        var args = AJS.forceArray(arguments);
-        args.splice(args.length-1, 0, 'height');
-        AJS.setStyle.apply(null, args);
-    },
-    setLeft: function(/*elm1, elm2..., left*/) {
-        var args = AJS.forceArray(arguments);
-        args.splice(args.length-1, 0, 'left');
-        AJS.setStyle.apply(null, args);
-    },
-    setTop: function(/*elm1, elm2..., top*/) {
-        var args = AJS.forceArray(arguments);
-        args.splice(args.length-1, 0, 'top');
-        AJS.setStyle.apply(null, args);
-    },
-    setClass: function(/*elm1, elm2..., className*/) {
-        var args = AJS.forceArray(arguments);
-        var c = args.pop();
-        AJS.map(args, function(elm) { elm.className = c});
-    },
-    addClass: function(/*elm1, elm2..., className*/) {
-        var args = AJS.forceArray(arguments);
-        var cls = args.pop();
-        var add_class = function(o) {
-            if(!new RegExp("(^|\\s)" + cls + "(\\s|$)").test(o.className))
-                o.className += (o.className ? " " : "") + cls;
-        };
-        AJS.map(args, function(elm) { add_class(elm); });
-    },
-    hasClass: function(elm, cls) {
-        if(!elm.className)
-            return false;
-        return elm.className == cls || 
-               elm.className.search(new RegExp(" " + cls + "|^" + cls)) != -1
-    },
-    removeClass: function(/*elm1, elm2..., className*/) {
-        var args = AJS.forceArray(arguments);
-        var cls = args.pop();
-        var rm_class = function(o) {
-            o.className = o.className.replace(new RegExp("\\s?" + cls, 'g'), "");
-        };
-        AJS.map(args, function(elm) { rm_class(elm); });
-    },
-
-    setHTML: function(elm, html) {
-        elm.innerHTML = html;
-        return elm;
-    },
-
-    RND: function(tmpl, ns, scope) {
-        scope = scope || window;
-        var fn = function(w, g) {
-            g = g.split("|");
-            var cnt = ns[g[0]];
-            for(var i=1; i < g.length; i++)
-                cnt = scope[g[i]](cnt);
-            if(cnt == '')
-                return '';
-            if(cnt == 0 || cnt == -1)
-                cnt += '';
-            return cnt || w;
-        };
-        return tmpl.replace(/%\(([A-Za-z0-9_|.]*)\)/g, fn);
-    },
-
-    HTML2DOM: function(html,/*optional*/ first_child) {
-        var d = AJS.DIV();
-        d.innerHTML = html;
-        if(first_child)
-            return d.childNodes[0];
-        else
-            return d;
-    },
-
-    preloadImages: function(/*img_src1, ..., img_srcN*/) {
-        AJS.AEV(window, 'load', AJS.$p(function(args) {
-            AJS.map(args, function(src) {
-                var pic = new Image();
-                pic.src = src;
-            });
-        }, arguments));
-    },
-
-
-////
-// Effects
-////
-    setOpacity: function(elm, p) {
-        elm.style.opacity = p;
-        elm.style.filter = "alpha(opacity="+ p*100 +")";
-    },
-
-    resetOpacity: function(elm) {
-        elm.style.opacity = 1;
-        elm.style.filter = "";
-    },
-
-////
-// Ajax functions
-////
-    getXMLHttpRequest: function() {
-        var try_these = [
-            function () { return new XMLHttpRequest(); },
-            function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
-            function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
-            function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
-            function () { throw "Browser does not support XMLHttpRequest"; }
-        ];
-        for (var i = 0; i < try_these.length; i++) {
-            var func = try_these[i];
-            try {
-                return func();
-            } catch (e) {
-            }
-        }
-    },
-
-    getRequest: function(url, data, type) {
-        if(!type)
-            type = "POST";
-        var req = AJS.getXMLHttpRequest();
-
-        if(url.indexOf("http://") == -1) {
-            if(AJS.BASE_URL != '') {
-                if(AJS.BASE_URL.lastIndexOf('/') != AJS.BASE_URL.length-1)
-                    AJS.BASE_URL += '/';
-                url = AJS.BASE_URL + url;
-            }
-        }
-
-        req.open(type, url, true);
-        if(type == "POST")
-            req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
-        return AJS._sendXMLHttpRequest(req);
-    },
-
-    _sendXMLHttpRequest: function(req, data) {
-        var d = new AJSDeferred(req);
-
-        var onreadystatechange = function () {
-            if (req.readyState == 4) {
-                var status = '';
-                try {
-                    status = req.status;
-                }
-                catch(e) {};
-                if(status == 200 || status == 304 || req.responseText == null) {
-                    d.callback();
-                }
-                else {
-                    if(d.errbacks.length == 0) {
-                        if(AJS.ajaxErrorHandler)
-                            AJS.ajaxErrorHandler(req.responseText, req);
-                    }
-                    else 
-                        d.errback();
-                }
-            }
-        }
-        req.onreadystatechange = onreadystatechange;
-        return d;
-    },
-
-    _reprString: function(o) {
-        return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
-        ).replace(/[\f]/g, "\\f"
-        ).replace(/[\b]/g, "\\b"
-        ).replace(/[\n]/g, "\\n"
-        ).replace(/[\t]/g, "\\t"
-        ).replace(/[\r]/g, "\\r");
-    },
-
-    _reprDate: function(db) {
-        var year = db.getFullYear();
-        var dd = db.getDate();
-        var mm = db.getMonth()+1;
-
-        var hh = db.getHours();
-        var mins = db.getMinutes();
-
-        function leadingZero(nr) {
-            if (nr < 10) nr = "0" + nr;
-            return nr;
-        }
-        if(hh == 24) hh = '00';
-
-        var time = leadingZero(hh) + ':' + leadingZero(mins);
-        return '"' + year + '-' + mm + '-' + dd + 'T' + time + '"';
-    },
-
-    serializeJSON: function(o) {
-        var objtype = typeof(o);
-        if (objtype == "undefined") {
-            return "undefined";
-        } else if (objtype == "number" || objtype == "boolean") {
-            return o + "";
-        } else if (o === null) {
-            return "null";
-        }
-        if (objtype == "string") {
-            return AJS._reprString(o);
-        }
-        if(objtype == 'object' && o.getFullYear) {
-            return AJS._reprDate(o);
-        }
-        var me = arguments.callee;
-        if (objtype != "function" && typeof(o.length) == "number") {
-            var res = [];
-            for (var i = 0; i < o.length; i++) {
-                var val = me(o[i]);
-                if (typeof(val) != "string") {
-                    val = "undefined";
-                }
-                res.push(val);
-            }
-            return "[" + res.join(",") + "]";
-        }
-        // it's a function with no adapter, bad
-        if (objtype == "function")
-            return null;
-        res = [];
-        for (var k in o) {
-            var useKey;
-            if (typeof(k) == "number") {
-                useKey = '"' + k + '"';
-            } else if (typeof(k) == "string") {
-                useKey = AJS._reprString(k);
-            } else {
-                // skip non-string or number keys
-                continue;
-            }
-            val = me(o[k]);
-            if (typeof(val) != "string") {
-                // skip non-serializable values
-                continue;
-            }
-            res.push(useKey + ":" + val);
-        }
-        return "{" + res.join(",") + "}";
-    },
-
-    loadJSONDoc: function(url) {
-        var d = AJS.getRequest(url);
-        var eval_req = function(data, req) {
-            var text = req.responseText;
-            if(text == "Error")
-                d.errback(req);
-            else
-                return AJS.evalTxt(text);
-        };
-        d.addCallback(eval_req);
-        return d;
-    },
-
-    evalTxt: function(txt) {
-        try {
-            return eval('('+ txt + ')');
-        }
-        catch(e) {
-            return eval(txt);
-        }
-    },
-
-    evalScriptTags: function(html) {
-        var script_data = html.match(/<script.*?>((\n|\r|.)*?)<\/script>/g);
-        if(script_data != null) {
-            for(var i=0; i < script_data.length; i++) {
-                var script_only = script_data[i].replace(/<script.*?>/g, "");
-                script_only = script_only.replace(/<\/script>/g, "");
-                eval(script_only);
-            }
-        }
-    },
-
-    queryArguments: function(data) {
-        var post_data = [];
-        for(k in data)
-            post_data.push(k + "=" + AJS.urlencode(data[k]));
-        return post_data.join("&");
-    },
-
-
-////
-// Position and size
-////
-    getMousePos: function(e) {
-        var posx = 0;
-        var posy = 0;
-        if (!e) var e = window.event;
-        if (e.pageX || e.pageY) {
-            posx = e.pageX;
-            posy = e.pageY;
-        }
-        else if (e.clientX || e.clientY) {
-            posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
-            posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
-        }
-        return {x: posx, y: posy};
-    },
-
-    getScrollTop: function() {
-        //From: http://www.quirksmode.org/js/doctypes.html
-        var t;
-        if (document.documentElement && document.documentElement.scrollTop)
-                t = document.documentElement.scrollTop;
-        else if (document.body)
-                t = document.body.scrollTop;
-        return t;
-    },
-
-    absolutePosition: function(elm) {
-        var posObj = {'x': elm.offsetLeft, 'y': elm.offsetTop};
-
-        if(elm.offsetParent) {
-            var next = elm.offsetParent;
-            while(next) {
-                posObj.x += next.offsetLeft;
-                posObj.y += next.offsetTop;
-                next = next.offsetParent;
-            }
-        }
-        // safari bug
-        if (AJS.isSafari() && elm.style.position == 'absolute' ) {
-            posObj.x -= document.body.offsetLeft;
-            posObj.y -= document.body.offsetTop;
-        }
-        return posObj;
-    },
-
-    getWindowSize: function(doc) {
-        doc = doc || document;
-        var win_w, win_h;
-        if (self.innerHeight) {
-            win_w = self.innerWidth;
-            win_h = self.innerHeight;
-        } else if (doc.documentElement && doc.documentElement.clientHeight) {
-            win_w = doc.documentElement.clientWidth;
-            win_h = doc.documentElement.clientHeight;
-        } else if (doc.body) {
-            win_w = doc.body.clientWidth;
-            win_h = doc.body.clientHeight;
-        }
-        return {'w': win_w, 'h': win_h};
-    },
-
-    isOverlapping: function(elm1, elm2) {
-        var pos_elm1 = AJS.absolutePosition(elm1);
-        var pos_elm2 = AJS.absolutePosition(elm2);
-
-        var top1 = pos_elm1.y;
-        var left1 = pos_elm1.x;
-        var right1 = left1 + elm1.offsetWidth;
-        var bottom1 = top1 + elm1.offsetHeight;
-        var top2 = pos_elm2.y;
-        var left2 = pos_elm2.x;
-        var right2 = left2 + elm2.offsetWidth;
-        var bottom2 = top2 + elm2.offsetHeight;
-        var getSign = function(v) {
-            if(v > 0) return "+";
-            else if(v < 0) return "-";
-            else return 0;
-        }
-
-        if ((getSign(top1 - bottom2) != getSign(bottom1 - top2)) &&
-                (getSign(left1 - right2) != getSign(right1 - left2)))
-            return true;
-        return false;
-    },
-
-
-////
-// Events
-////
-    getEventElm: function(e) {
-        if(e && !e.type && !e.keyCode)
-            return e
-        var targ;
-        if (!e) var e = window.event;
-        if (e.target) targ = e.target;
-        else if (e.srcElement) targ = e.srcElement;
-        if (targ.nodeType == 3) // defeat Safari bug
-            targ = targ.parentNode;
-        return targ;
-    },
-
-    _getRealScope: function(fn, /*optional*/ extra_args) {
-        extra_args = AJS.$A(extra_args);
-        var scope = fn._cscope || window;
-
-        return function() {
-            var args = AJS.$FA(arguments).concat(extra_args);
-            return fn.apply(scope, args);
-        };
-    },
-
-    _unloadListeners: function() {
-        if(AJS.listeners)
-            AJS.map(AJS.listeners, function(elm, type, fn) { AJS.REV(elm, type, fn) });
-        AJS.listeners = [];
-    },
-
-    setEventKey: function(e) {
-        e.key = e.keyCode ? e.keyCode : e.charCode;
-
-        if(window.event) {
-            e.ctrl = window.event.ctrlKey;
-            e.shift = window.event.shiftKey;
-        }
-        else {
-            e.ctrl = e.ctrlKey;
-            e.shift = e.shiftKey;
-        }
-        switch(e.key) {
-            case 63232:
-                e.key = 38;
-                break;
-            case 63233:
-                e.key = 40;
-                break;
-            case 63235:
-                e.key = 39;
-                break;
-            case 63234:
-                e.key = 37;
-                break;
-        }
-    },
-
-    //Shortcut: AJS.AEV
-    addEventListener: function(elm, type, fn, /*optional*/listen_once, cancle_bubble) {
-        if(!cancle_bubble)
-            cancle_bubble = false;
-
-        var elms = AJS.$A(elm);
-        AJS.map(elms, function(elmz) {
-            if(listen_once)
-                fn = AJS._listenOnce(elmz, type, fn);
-            
-            //Hack since it does not work in all browsers
-            if(AJS.isIn(type, ['submit', 'load', 'scroll', 'resize'])) {
-                var old = elm['on' + type];
-                elm['on' + type] = function() {
-                    if(old) {
-                        fn(arguments);
-                        return old(arguments);
-                    }
-                    else
-                        return fn(arguments);
-                };
-                return;
-            }
-
-            //Fix keyCode
-            if(AJS.isIn(type, ['keypress', 'keydown', 'keyup', 'click'])) {
-                var old_fn = fn;
-                fn = function(e) {
-                    AJS.setEventKey(e);
-                    return old_fn.apply(null, arguments);
-                }
-            }
-
-            if (elmz.attachEvent) {
-                //FIXME: We ignore cancle_bubble for IE... could be a problem?
-                elmz.attachEvent("on" + type, fn);
-            }
-            else if(elmz.addEventListener)
-                elmz.addEventListener(type, fn, cancle_bubble);
-
-            AJS.listeners = AJS.$A(AJS.listeners);
-            AJS.listeners.push([elmz, type, fn]);
-        });
-    },
-
-    //Shortcut: AJS.REV
-    removeEventListener: function(elm, type, fn, /*optional*/cancle_bubble) {
-        if(!cancle_bubble)
-            cancle_bubble = false;
-        if(elm.removeEventListener) {
-            elm.removeEventListener(type, fn, cancle_bubble);
-            if(AJS.isOpera())
-                elm.removeEventListener(type, fn, !cancle_bubble);
-        }
-        else if(elm.detachEvent)
-            elm.detachEvent("on" + type, fn);
-    },
-
-    //Shortcut: AJS.$b
-    bind: function(fn, scope, /*optional*/ extra_args) {
-        fn._cscope = scope;
-        return AJS._getRealScope(fn, extra_args);
-    },
-
-    bindMethods: function(self) {
-        for (var k in self) {
-            var func = self[k];
-            if (typeof(func) == 'function') {
-                self[k] = AJS.$b(func, self);
-            }
-        }
-    },
-
-    _listenOnce: function(elm, type, fn) {
-        var r_fn = function() {
-            AJS.removeEventListener(elm, type, r_fn);
-            fn(arguments);
-        }
-        return r_fn;
-    },
-
-    callLater: function(fn, interval) {
-        var fn_no_send = function() {
-            fn();
-        };
-        window.setTimeout(fn_no_send, interval);
-    },
-
-    preventDefault: function(e) {
-        if(AJS.isIe()) 
-            window.event.returnValue = false;
-        else 
-            e.preventDefault();
-    },
-
-
-////
-// Drag and drop
-////
-    dragAble: function(elm, /*optional*/ handler, args) {
-        if(!args)
-            args = {};
-        if(!AJS.isDefined(args['move_x']))
-            args['move_x'] = true;
-        if(!AJS.isDefined(args['move_y']))
-            args['move_y'] = true;
-        if(!AJS.isDefined(args['moveable']))
-            args['moveable'] = false;
-        if(!AJS.isDefined(args['hide_on_move']))
-            args['hide_on_move'] = true;
-        if(!AJS.isDefined(args['on_mouse_up']))
-            args['on_mouse_up'] = null;
-        if(!AJS.isDefined(args['cursor']))
-            args['cursor'] = 'move';
-        if(!AJS.isDefined(args['max_move']))
-            args['max_move'] = {'top': null, 'left': null};
-
-        elm = AJS.$(elm);
-
-        if(!handler)
-            handler = elm;
-
-        handler = AJS.$(handler);
-        var old_cursor = handler.style.cursor;
-        handler.style.cursor = args['cursor'];
-        elm.style.position = 'relative';
-
-        AJS.addClass(handler, '_ajs_handler');
-        handler._args = args;
-        handler._elm = elm;
-        AJS.AEV(handler, 'mousedown', AJS._dragStart);
-    },
-
-    _dragStart: function(e) {
-        var handler = AJS.getEventElm(e);
-        if(!AJS.hasClass(handler, '_ajs_handler')) {
-            handler = AJS.getParentBytc(handler, null, '_ajs_handler');
-        }
-        if(handler)
-            AJS._dragInit(e, handler._elm, handler._args);
-    },
-
-    dropZone: function(elm, args) {
-        elm = AJS.$(elm);
-        var item = {elm: elm};
-        AJS.update(item, args);
-        AJS._drop_zones.push(item);
-    },
-
-    removeDragAble: function(elm) {
-        AJS.REV(elm, 'mousedown', AJS._dragStart);
-        elm.style.cursor = '';
-    },
-
-    removeDropZone: function(elm) {
-        var i = AJS.getIndex(elm, AJS._drop_zones, function(item) {
-            if(item.elm == elm) return true;
-        });
-        if(i != -1) {
-            AJS._drop_zones.splice(i, 1);
-        }
-    },
-
-    _dragInit: function(e, click_elm, args) {
-        AJS.drag_obj = new Object();
-        AJS.drag_obj.args = args;
-
-        AJS.drag_obj.click_elm = click_elm;
-        AJS.drag_obj.mouse_pos = AJS.getMousePos(e);
-        AJS.drag_obj.click_elm_pos = AJS.absolutePosition(click_elm);
-
-        AJS.AEV(document, 'mousemove', AJS._dragMove, false, true);
-        AJS.AEV(document, 'mouseup', AJS._dragStop, false, true);
-
-        if (AJS.isIe())
-            window.event.cancelBubble = true;
-        AJS.preventDefault(e);
-    },
-
-    _initDragElm: function(elm) {
-        if(AJS.drag_elm && AJS.drag_elm.style.display == 'none')
-            AJS.removeElement(AJS.drag_elm);
-
-        if(!AJS.drag_elm) {
-            AJS.drag_elm = AJS.DIV();
-            var d = AJS.drag_elm;
-            AJS.insertBefore(d, AJS.getBody().firstChild);
-            AJS.setHTML(d, elm.innerHTML);
-
-            d.className = elm.className;
-            d.style.cssText = elm.style.cssText;
-
-            d.style.position = 'absolute';
-            d.style.zIndex = 10000;
-
-            var t = AJS.absolutePosition(elm);
-            AJS.setTop(d, t.y);
-            AJS.setLeft(d, t.x);
-
-            if(AJS.drag_obj.args.on_init) {
-                AJS.drag_obj.args.on_init(elm);
-            }
-        }
-    },
-
-    _dragMove: function(e) {
-        var drag_obj = AJS.drag_obj;
-        var click_elm = drag_obj.click_elm;
-
-        AJS._initDragElm(click_elm);
-        var drag_elm = AJS.drag_elm;
-
-        if(drag_obj.args['hide_on_move'])
-            click_elm.style.visibility = 'hidden';
-
-        var cur_pos = AJS.getMousePos(e);
-
-        var mouse_pos = drag_obj.mouse_pos;
-
-        var click_elm_pos = drag_obj.click_elm_pos;
-
-        var p_x, p_y;
-        p_x = cur_pos.x - (mouse_pos.x - click_elm_pos.x);
-        p_y = cur_pos.y - (mouse_pos.y - click_elm_pos.y);
-
-        AJS.map(AJS._drop_zones, function(d_z) {
-            if(AJS.isOverlapping(d_z['elm'], drag_elm)) {
-                if(d_z['elm'] != drag_elm) {
-                    var on_hover = d_z['on_hover'];
-                    if(on_hover)
-                        on_hover(d_z['elm'], click_elm, drag_elm);
-                }
-            }
-        });
-
-        if(drag_obj.args['on_drag'])
-            drag_obj.args['on_drag'](click_elm, e);
-
-        var max_move_top = drag_obj.args['max_move']['top'];
-        var max_move_left = drag_obj.args['max_move']['left'];
-        if(drag_obj.args['move_x']) {
-            if(max_move_left == null || max_move_left <= p)
-                AJS.setLeft(elm, p_x);
-        }
-
-        if(drag_obj.args['move_y']) {
-            if(max_move_top == null || max_move_top <= p_y)
-                AJS.setTop(elm, p_y);
-        }
-        if(AJS.isIe()) {
-            window.event.cancelBubble = true;
-            window.event.returnValue = false;
-        }
-        else
-            e.preventDefault();
-
-        //Moving scroll to the top, should move the scroll up
-        var sc_top = AJS.getScrollTop();
-        var sc_bottom = sc_top + AJS.getWindowSize().h;
-        var d_e_top = AJS.absolutePosition(drag_elm).y;
-        var d_e_bottom = drag_elm.offsetTop + drag_elm.offsetHeight;
-
-        if(d_e_top <= sc_top + 20) {
-            window.scrollBy(0, -15);
-        }
-        else if(d_e_bottom >= sc_bottom - 20) {
-            window.scrollBy(0, 15);
-        }
-    },
-
-    _dragStop: function(e) {
-        var drag_obj = AJS.drag_obj;
-        var drag_elm = AJS.drag_elm;
-        var click_elm = drag_obj.click_elm;
-
-        AJS.REV(document, "mousemove", AJS._dragMove, true);
-        AJS.REV(document, "mouseup", AJS._dragStop, true);
-
-        var dropped = false;
-        AJS.map(AJS._drop_zones, function(d_z) {
-            if(AJS.isOverlapping(d_z['elm'], click_elm)) {
-                if(d_z['elm'] != click_elm) {
-                    var on_drop = d_z['on_drop'];
-                    if(on_drop) {
-                        dropped = true;
-                        on_drop(d_z['elm'], click_elm);
-                    }
-                }
-            }
-        });
-
-        if(drag_obj.args['moveable']) {
-            var t = parseInt(click_elm.style.top) || 0;
-            var l = parseInt(click_elm.style.left) || 0;
-            var drag_elm_xy = AJS.absolutePosition(drag_elm);
-            var click_elm_xy = AJS.absolutePosition(click_elm);
-            AJS.setTop(click_elm, t + drag_elm_xy.y - click_elm_xy.y);
-            AJS.setLeft(click_elm, l + drag_elm_xy.x - click_elm_xy.x);
-        }
-
-        if(!dropped && drag_obj.args['on_mouse_up'])
-            drag_obj.args['on_mouse_up'](click_elm, e);
-
-        if(drag_obj.args['hide_on_move'])
-            drag_obj.click_elm.style.visibility = 'visible';
-
-        if(drag_obj.args.on_end) {
-            drag_obj.args.on_end(click_elm);
-        }
-
-        AJS._dragObj = null;
-        if(drag_elm)
-            AJS.hideElement(drag_elm);
-        AJS.drag_elm = null;
-    },
-
-
-////
-// Misc.
-////
-    keys: function(obj) {
-        var rval = [];
-        for (var prop in obj) {
-            rval.push(prop);
-        }
-        return rval;
-    },
-
-    values: function(obj) {
-        var rval = [];
-        for (var prop in obj) {
-            rval.push(obj[prop]);
-        }
-        return rval;
-    },
-
-    urlencode: function(str) {
-        return encodeURIComponent(str.toString());
-    },
-
-    isDefined: function(o) {
-        return (o != "undefined" && o != null)
-    },
-
-    isArray: function(obj) {
-        return obj instanceof Array;
-    },
-
-    isString: function(obj) {
-        return (typeof obj == 'string');
-    },
-
-    isNumber: function(obj) {
-        return (typeof obj == 'number');
-    },
-
-    isObject: function(obj) {
-        return (typeof obj == 'object');
-    },
-
-    isFunction: function(obj) {
-        return (typeof obj == 'function');
-    },
-
-    isDict: function(o) {
-        var str_repr = String(o);
-        return str_repr.indexOf(" Object") != -1;
-    },
-
-    exportToGlobalScope: function() {
-        for(e in AJS)
-            window[e] = AJS[e];
-    },
-
-    log: function(o) {
-        if(window.console)
-            console.log(o);
-        else {
-            var div = AJS.$('ajs_logger');
-            if(!div) {
-                div = AJS.DIV({id: 'ajs_logger', 'style': 'color: green; position: absolute; left: 0'});
-                div.style.top = AJS.getScrollTop() + 'px';
-                AJS.ACN(AJS.getBody(), div);
-            }
-            AJS.setHTML(div, ''+o);
-        }
+    this.array_keys = function(arr) {
+        var res = [];
+        for (var key in arr) { res.push([key]); }
+        return res;
     }
-
-}
-
-AJS.Class = function(members) {
-    var fn = function() {
-        if(arguments[0] != 'no_init') {
-            return this.init.apply(this, arguments);
-        }
-    }
-    fn.prototype = members;
-    AJS.update(fn, AJS.Class.prototype);
-    return fn;
-}
-AJS.Class.prototype = {
-    extend: function(members) {
-        var parent = new this('no_init');
-        for(k in members) {
-            var prev = parent[k];
-            var cur = members[k];
-            if (prev && prev != cur && typeof cur == 'function') {
-                cur = this._parentize(cur, prev);
-            }
-            parent[k] = cur;
-        }
-        return new AJS.Class(parent);
-    },
-
-    implement: function(members) {
-        AJS.update(this.prototype, members);
-    },
-
-    _parentize: function(cur, prev) {
-        return function(){
-            this.parent = prev;
-            return cur.apply(this, arguments);
-        }
-    }
-};
-
-//Shortcuts
-AJS.$ = AJS.getElement;
-AJS.$$ = AJS.getElements;
-AJS.$f = AJS.getFormElement;
-AJS.$b = AJS.bind;
-AJS.$p = AJS.partial;
-AJS.$FA = AJS.forceArray;
-AJS.$A = AJS.createArray;
-AJS.DI = AJS.documentInsert;
-AJS.ACN = AJS.appendChildNodes;
-AJS.RCN = AJS.replaceChildNodes;
-AJS.AEV = AJS.addEventListener;
-AJS.REV = AJS.removeEventListener;
-AJS.$bytc = AJS.getElementsByTagAndClassName;
-
-AJSDeferred = function(req) {
-    this.callbacks = [];
-    this.errbacks = [];
-    this.req = req;
-}
-AJSDeferred.prototype = {
-    excCallbackSeq: function(req, list) {
-        var data = req.responseText;
-        while (list.length > 0) {
-            var fn = list.pop();
-            var new_data = fn(data, req);
-            if(new_data)
-                data = new_data;
-        }
-    },
-
-    callback: function () {
-        this.excCallbackSeq(this.req, this.callbacks);
-    },
-
-    errback: function() {
-        if(this.errbacks.length == 0)
-            alert("Error encountered:\n" + this.req.responseText);
-
-        this.excCallbackSeq(this.req, this.errbacks);
-    },
-
-    addErrback: function(fn) {
-        this.errbacks.unshift(fn);
-    },
-
-    addCallback: function(fn) {
-        this.callbacks.unshift(fn);
-    },
-
-    abort: function() {
-        this.req.abort();
-    },
-
-    addCallbacks: function(fn1, fn2) {
-        this.addCallback(fn1);
-        this.addErrback(fn2);
-    },
-
-    sendReq: function(data) {
-        if(AJS.isObject(data)) {
-            this.req.send(AJS.queryArguments(data));
-        }
-        else if(AJS.isDefined(data))
-            this.req.send(data);
-        else {
-            this.req.send("");
-        }
-    }
-};
-
-//Prevent memory-leaks
-AJS.addEventListener(window, 'unload', AJS._unloadListeners);
-AJS._createDomShortcuts()
-}
-
-script_loaded = true;
-
-/****
-Last Modified: 13/05/07 00:25:28
-
- GoogieSpell
-     Google spell checker for your own web-apps :)
- Copyright Amir Salihefendic 2006
-     LICENSE
-     GPL (see gpl.txt for more information)
-     This basically means that you can't use this script with/in proprietary software!
-     There is another license that permits you to use this script with proprietary software. Check out:... for more info.
-     AUTHOR
-         4mir Salihefendic (http://amix.dk) - amix@amix.dk
- VERSION
-     4.0
-****/
-var GOOGIE_CUR_LANG = null;
-var GOOGIE_DEFAULT_LANG = "en";
-
-function GoogieSpell(img_dir, server_url) {
-    var cookie_value;
-    var lang;
-    cookie_value = getCookie('language');
-
-    if(cookie_value != null)
-        GOOGIE_CUR_LANG = cookie_value;
-    else
-        GOOGIE_CUR_LANG = GOOGIE_DEFAULT_LANG;
 
     this.img_dir = img_dir;
     this.server_url = server_url;
 
-    this.org_lang_to_word = {"da": "Dansk", "de": "Deutsch", "en": "English",
-                                             "es": "Espa&#241;ol", "fr": "Fran&#231;ais", "it": "Italiano", 
-                                             "nl": "Nederlands", "pl": "Polski", "pt": "Portugu&#234;s",
-                                             "fi": "Suomi", "sv": "Svenska"};
+    this.org_lang_to_word = {
+        "da": "Dansk", "de": "Deutsch", "en": "English",
+        "es": "Español", "fr": "Français", "it": "Italiano",
+        "nl": "Nederlands", "pl": "Polski", "pt": "Português",
+        "ru": "Русский", "fi": "Suomi", "sv": "Svenska"
+    };
     this.lang_to_word = this.org_lang_to_word;
-    this.langlist_codes = AJS.keys(this.lang_to_word);
-
+    this.langlist_codes = this.array_keys(this.lang_to_word);
     this.show_change_lang_pic = true;
-    this.change_lang_pic_placement = "left";
-
+    this.change_lang_pic_placement = 'right';
     this.report_state_change = true;
 
     this.ta_scroll_top = 0;
@@ -1474,132 +72,129 @@
     this.lang_rsm_edt = "Resume editing";
     this.lang_no_error_found = "No spelling errors found";
     this.lang_no_suggestions = "No suggestions";
-    
-    this.show_spell_img = false;  // modified by roundcube
+    this.lang_learn_word = "Add to dictionary";
+
+    this.show_spell_img = false; // roundcube mod.
     this.decoration = true;
-    this.use_close_btn = true;
+    this.use_close_btn = false;
     this.edit_layer_dbl_click = true;
     this.report_ta_not_found = true;
 
-    //Extensions
+    // Extensions
     this.custom_ajax_error = null;
     this.custom_no_spelling_error = null;
-    this.custom_menu_builder = []; //Should take an eval function and a build menu function
-    this.custom_item_evaulator = null; //Should take an eval function and a build menu function
+    this.custom_menu_builder = []; // Should take an eval function and a build menu function
+    this.custom_item_evaulator = null; // Should take an eval function and a build menu function
     this.extra_menu_items = [];
     this.custom_spellcheck_starter = null;
     this.main_controller = true;
+    this.has_dictionary = has_dict;
 
-    //Observers
+    // Observers
     this.lang_state_observer = null;
     this.spelling_state_observer = null;
     this.show_menu_observer = null;
     this.all_errors_fixed_observer = null;
 
-    //Focus links - used to give the text box focus
+    // Focus links - used to give the text box focus
     this.use_focus = false;
     this.focus_link_t = null;
     this.focus_link_b = null;
 
-    //Counters
+    // Counters
     this.cnt_errors = 0;
     this.cnt_errors_fixed = 0;
 
-    //Set document on click to hide the language and error menu
-    var fn = function(e) {
-        var elm = AJS.getEventElm(e);
-        if(elm.googie_action_btn != "1" && this.isLangWindowShown())
-            this.hideLangWindow();
-        if(elm.googie_action_btn != "1" && this.isErrorWindowShown())
-            this.hideErrorWindow();
-    };
-    AJS.AEV(document, "click", AJS.$b(fn, this));
-}
+    // Set document's onclick to hide the language and error menu
+    $(document).click(function(e) {
+        var target = $(e.target);
+        if (target.attr('googie_action_btn') != '1' && ref.isLangWindowShown())
+            ref.hideLangWindow();
+        if (target.attr('googie_action_btn') != '1' && ref.isErrorWindowShown())
+            ref.hideErrorWindow();
+    });
 
-GoogieSpell.prototype.decorateTextarea = function(id) {
-    if(typeof(id) == "string")
-        this.text_area = AJS.$(id);
-    else
-        this.text_area = id;
 
-    var r_width, r_height;
+this.decorateTextarea = function(id)
+{
+    this.text_area = typeof id === 'string' ? document.getElementById(id) : id;
 
-    if(this.text_area != null) {
-        if(!AJS.isDefined(this.spell_container) && this.decoration) {
-            var table = AJS.TABLE();
-            var tbody = AJS.TBODY();
-            var tr = AJS.TR();
-            if(AJS.isDefined(this.force_width))
-                r_width = this.force_width;
-            else
-                r_width = this.text_area.offsetWidth + "px";
-
-            if(AJS.isDefined(this.force_height))
-                r_height = this.force_height;
-            else
-                r_height = "";
-
-            var spell_container = AJS.TD();
-            this.spell_container = spell_container;
+    if (this.text_area) {
+        if (!this.spell_container && this.decoration) {
+            var table = document.createElement('table'),
+                tbody = document.createElement('tbody'),
+                tr = document.createElement('tr'),
+                spell_container = document.createElement('td'),
+                r_width = this.isDefined(this.force_width) ? this.force_width : this.text_area.offsetWidth,
+                r_height = this.isDefined(this.force_height) ? this.force_height : 16;
 
             tr.appendChild(spell_container);
-
             tbody.appendChild(tr);
-            table.appendChild(tbody);
+            $(table).append(tbody).insertBefore(this.text_area).width('100%').height(r_height);
+            $(spell_container).height(r_height).width(r_width).css('text-align', 'right');
 
-            AJS.insertBefore(table, this.text_area);
-
-            //Set width
-            AJS.setHeight(table, spell_container, r_height);
-            AJS.setWidth(table, spell_container, '100%');  // modified by roundcube (old: r_width)
-
-            spell_container.style.textAlign = "right";
+            this.spell_container = spell_container;
         }
 
         this.checkSpellingState();
     }
-    else 
-        if(this.report_ta_not_found)
-            alert("Text area not found");
-}
+    else if (this.report_ta_not_found)
+        alert('Text area not found');
+};
 
 //////
 // API Functions (the ones that you can call)
 /////
-GoogieSpell.prototype.setSpellContainer = function(elm) {
-    this.spell_container = AJS.$(elm);
-}
+this.setSpellContainer = function(id)
+{
+    this.spell_container = typeof id === 'string' ? document.getElementById(id) : id;
+};
 
-GoogieSpell.prototype.setLanguages = function(lang_dict) {
+this.setLanguages = function(lang_dict)
+{
     this.lang_to_word = lang_dict;
-    this.langlist_codes = AJS.keys(lang_dict);
-}
+    this.langlist_codes = this.array_keys(lang_dict);
+};
 
-GoogieSpell.prototype.setForceWidthHeight = function(width, height) {
-    /***
-        Set to null if you want to use one of them
-    ***/
+this.setCurrentLanguage = function(lan_code)
+{
+    GOOGIE_CUR_LANG = lan_code;
+
+    //Set cookie
+    var now = new Date();
+    now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
+    rcmail.set_cookie('language', lan_code, now);
+};
+
+this.setForceWidthHeight = function(width, height)
+{
+    // Set to null if you want to use one of them
     this.force_width = width;
     this.force_height = height;
-}
+};
 
-GoogieSpell.prototype.setDecoration = function(bool) {
+this.setDecoration = function(bool)
+{
     this.decoration = bool;
-}
+};
 
-GoogieSpell.prototype.dontUseCloseButtons = function() {
+this.dontUseCloseButtons = function()
+{
     this.use_close_btn = false;
-}
+};
 
-GoogieSpell.prototype.appendNewMenuItem = function(name, call_back_fn, checker) {
+this.appendNewMenuItem = function(name, call_back_fn, checker)
+{
     this.extra_menu_items.push([name, call_back_fn, checker]);
-}
+};
 
-GoogieSpell.prototype.appendCustomMenuBuilder = function(eval, builder) {
-    this.custom_menu_builder.push([eval, builder]);
-}
+this.appendCustomMenuBuilder = function(eval_fn, builder)
+{
+    this.custom_menu_builder.push([eval_fn, builder]);
+};
 
-GoogieSpell.prototype.setFocus = function() {
+this.setFocus = function()
+{
     try {
         this.focus_link_b.focus();
         this.focus_link_t.focus();
@@ -1608,247 +203,246 @@
     catch(e) {
         return false;
     }
-}
-
-GoogieSpell.prototype.getValue = function(ta) {
-    return ta.value;
-}
-
-GoogieSpell.prototype.setValue = function(ta, value) {
-    ta.value = value;
-}
+};
 
 
 //////
 // Set functions (internal)
 /////
-GoogieSpell.prototype.setStateChanged = function(current_state) {
+this.setStateChanged = function(current_state)
+{
     this.state = current_state;
-    if(this.spelling_state_observer != null && this.report_state_change)
+    if (this.spelling_state_observer != null && this.report_state_change)
         this.spelling_state_observer(current_state, this);
-}
+};
 
-GoogieSpell.prototype.setReportStateChange = function(bool) {
+this.setReportStateChange = function(bool)
+{
     this.report_state_change = bool;
-}
+};
 
 
 //////
 // Request functions
 /////
-GoogieSpell.prototype.getGoogleUrl = function() {
+this.getUrl = function()
+{
     return this.server_url + GOOGIE_CUR_LANG;
-}
+};
 
-GoogieSpell.escapeSepcial = function(val) {
-    return val.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-}
+this.escapeSpecial = function(val)
+{
+    return val ? val.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
+};
 
-GoogieSpell.createXMLReq = function (text) {
-    return '<?xml version="1.0" encoding="utf-8" ?><spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1"><text>' + text + '</text></spellrequest>';
-}
+this.createXMLReq = function (text)
+{
+    return '<?xml version="1.0" encoding="utf-8" ?>'
+        + '<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">'
+        + '<text>' + text + '</text></spellrequest>';
+};
 
-GoogieSpell.prototype.spellCheck = function(ignore) {
-    var me = this;
+this.spellCheck = function(ignore)
+{
+    this.prepare(ignore);
 
-    this.cnt_errors_fixed = 0;
-    this.cnt_errors = 0;
-    this.setStateChanged("checking_spell");
+    var req_text = this.escapeSpecial(this.orginal_text),
+        ref = this;
 
-    if(this.main_controller)
-        this.appendIndicator(this.spell_span);
-
-    this.error_links = [];
-    this.ta_scroll_top = this.text_area.scrollTop;
-
-    try { this.hideLangWindow(); }
-    catch(e) {}
-
-    this.ignore = ignore;
-
-    if(this.getValue(this.text_area) == '' || ignore) {
-        if(!me.custom_no_spelling_error)
-            me.flashNoSpellingErrorState();
-        else
-            me.custom_no_spelling_error(me);
-        me.removeIndicator();
-        return ;
-    }
-    
-    this.createEditLayer(this.text_area.offsetWidth, this.text_area.offsetHeight);
-
-    this.createErrorWindow();
-    AJS.getBody().appendChild(this.error_window);
-
-    try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); } 
-    catch (e) { }
-
-    if(this.main_controller)
-        this.spell_span.onclick = null;
-
-    this.orginal_text = this.getValue(this.text_area);
-
-    //Create request
-    var d = AJS.getRequest(this.getGoogleUrl());
-    var reqdone = function(res_txt) {
-        var r_text = res_txt;
-        me.results = me.parseResult(r_text);
-
-        if(r_text.match(/<c.*>/) != null) {
-            //Before parsing be sure that errors were found
-            me.showErrorsInIframe();
-            me.resumeEditingState();
-        }
-        else {
-            if(!me.custom_no_spelling_error)
-                me.flashNoSpellingErrorState();
+    $.ajax({ type: 'POST', url: this.getUrl(), data: this.createXMLReq(req_text), dataType: 'text',
+        error: function(o) {
+            if (ref.custom_ajax_error)
+                ref.custom_ajax_error(ref);
             else
-                me.custom_no_spelling_error(me);
+                alert('An error was encountered on the server. Please try again later.');
+            if (ref.main_controller) {
+                $(ref.spell_span).remove();
+                ref.removeIndicator();
+            }
+            ref.checkSpellingState();
+        },
+        success: function(data) {
+            ref.processData(data);
+            if (!ref.results.length) {
+                if (!ref.custom_no_spelling_error)
+                    ref.flashNoSpellingErrorState();
+                else
+                    ref.custom_no_spelling_error(ref);
+            }
+            ref.removeIndicator();
         }
-        me.removeIndicator();
-    };
+    });
+};
 
-    d.addCallback(reqdone);
-    reqdone = null;
+this.learnWord = function(word, id)
+{
+    word = this.escapeSpecial(word.innerHTML);
 
-    var reqfailed = function(res_txt, req) {
-        if(me.custom_ajax_error)
-            me.custom_ajax_error(req);
-        else
-            alert("An error was encountered on the server. Please try again later.");
+    var ref = this,
+        req_text = '<?xml version="1.0" encoding="utf-8" ?><learnword><text>' + word + '</text></learnword>';
 
-        if(me.main_controller) {
-            AJS.removeElement(me.spell_span);
-            me.removeIndicator();
+    $.ajax({ type: 'POST', url: this.getUrl(), data: req_text, dataType: 'text',
+        error: function(o) {
+            if (ref.custom_ajax_error)
+                ref.custom_ajax_error(ref);
+            else
+                alert('An error was encountered on the server. Please try again later.');
+        },
+        success: function(data) {
         }
-        me.checkSpellingState();
-    };
-    d.addErrback(reqfailed);
-    reqfailed = null;
-
-    var req_text = GoogieSpell.escapeSepcial(this.orginal_text);
-    d.sendReq(GoogieSpell.createXMLReq(req_text));
-}
+    });
+};
 
 
 //////
 // Spell checking functions
 /////
-GoogieSpell.prototype.parseResult = function(r_text) {
-    /***
-     Retunrs an array
-     result[item] -> ['attrs'], ['suggestions']
-        ***/
-    var re_split_attr_c = /\w+="(\d+|true)"/g;
-    var re_split_text = /\t/g;
+this.prepare = function(ignore, no_indicator)
+{
+    this.cnt_errors_fixed = 0;
+    this.cnt_errors = 0;
+    this.setStateChanged('checking_spell');
+    this.orginal_text = '';
 
-    var matched_c = r_text.match(/<c[^>]*>[^<]*<\/c>/g);
-    var results = new Array();
+    if (!no_indicator && this.main_controller)
+        this.appendIndicator(this.spell_span);
 
-    if(matched_c == null)
+    this.error_links = [];
+    this.ta_scroll_top = this.text_area.scrollTop;
+    this.ignore = ignore;
+    this.hideLangWindow();
+
+    var area = $(this.text_area);
+
+    if (area.val() == '' || ignore) {
+        if (!this.custom_no_spelling_error)
+            this.flashNoSpellingErrorState();
+        else
+            this.custom_no_spelling_error(this);
+        this.removeIndicator();
+        return;
+    }
+
+    this.createEditLayer(area.width(), area.height());
+    this.createErrorWindow();
+    $('body').append(this.error_window);
+
+    try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }
+    catch (e) { }
+
+    if (this.main_controller)
+        $(this.spell_span).off('click');
+
+    this.orginal_text = area.val();
+};
+
+this.parseResult = function(r_text)
+{
+    // Returns an array: result[item] -> ['attrs'], ['suggestions']
+    var re_split_attr_c = /\w+="(\d+|true)"/g,
+        re_split_text = /\t/g,
+        matched_c = r_text.match(/<c[^>]*>[^<]*<\/c>/g),
+        results = [];
+
+    if (matched_c == null)
         return results;
-    
-    for(var i=0; i < matched_c.length; i++) {
-        var item = new Array();
+
+    for (var i=0, len=matched_c.length; i < len; i++) {
+        var item = [];
         this.errorFound();
 
-        //Get attributes
-        item['attrs'] = new Array();
-        var split_c = matched_c[i].match(re_split_attr_c);
-        for(var j=0; j < split_c.length; j++) {
-            var c_attr = split_c[j].split(/=/);
-            var val = c_attr[1].replace(/"/g, '');
-            if(val != "true")
-                item['attrs'][c_attr[0]] = parseInt(val);
-            else {
-                item['attrs'][c_attr[0]] = val;
-            }
+        // Get attributes
+        item['attrs'] = [];
+        var c_attr, val,
+            split_c = matched_c[i].match(re_split_attr_c);
+        for (var j=0; j < split_c.length; j++) {
+            c_attr = split_c[j].split(/=/);
+            val = c_attr[1].replace(/"/g, '');
+            item['attrs'][c_attr[0]] = val != 'true' ? parseInt(val) : val;
         }
 
-        //Get suggestions
-        item['suggestions'] = new Array();
-        var only_text = matched_c[i].replace(/<[^>]*>/g, "");
-        var split_t = only_text.split(re_split_text);
-        for(var k=0; k < split_t.length; k++) {
-        if(split_t[k] != "")
+        // Get suggestions
+        item['suggestions'] = [];
+        var only_text = matched_c[i].replace(/<[^>]*>/g, ''),
+            split_t = only_text.split(re_split_text);
+        for (var k=0; k < split_t.length; k++) {
+            if(split_t[k] != '')
             item['suggestions'].push(split_t[k]);
         }
         results.push(item);
     }
-    return results;
-}
 
-//////
-// Counters
-/////
-GoogieSpell.prototype.errorFixed = function() { 
-    this.cnt_errors_fixed++; 
-    if(this.all_errors_fixed_observer)
-        if(this.cnt_errors_fixed == this.cnt_errors) {
-            this.hideErrorWindow();
-            this.all_errors_fixed_observer();
-        }
-}
-GoogieSpell.prototype.errorFound = function() { this.cnt_errors++; }
+    return results;
+};
+
+this.processData = function(data)
+{
+    this.results = this.parseResult(data);
+    if (this.results.length) {
+        this.showErrorsInIframe();
+        this.resumeEditingState();
+    }
+};
 
 //////
 // Error menu functions
 /////
-GoogieSpell.prototype.createErrorWindow = function() {
-    this.error_window = AJS.DIV();
-    this.error_window.className = "googie_window";
-    this.error_window.googie_action_btn = "1";
-}
+this.createErrorWindow = function()
+{
+    this.error_window = document.createElement('div');
+    $(this.error_window).addClass('googie_window popupmenu').attr('googie_action_btn', '1');
+};
 
-GoogieSpell.prototype.isErrorWindowShown = function() {
-    return this.error_window != null && this.error_window.style.visibility == "visible";
-}
+this.isErrorWindowShown = function()
+{
+    return $(this.error_window).is(':visible');
+};
 
-GoogieSpell.prototype.hideErrorWindow = function() {
-    try {
-        this.error_window.style.visibility = "hidden";
-        if(this.error_window_iframe)
-            this.error_window_iframe.style.visibility = "hidden";
-    }
-    catch(e) {}
-}
+this.hideErrorWindow = function()
+{
+    $(this.error_window).hide();
+    $(this.error_window_iframe).hide();
+};
 
-GoogieSpell.prototype.updateOrginalText = function(offset, old_value, new_value, id) {
-    var part_1 = this.orginal_text.substring(0, offset);
-    var part_2 = this.orginal_text.substring(offset+old_value.length);
+this.updateOrginalText = function(offset, old_value, new_value, id)
+{
+    var part_1 = this.orginal_text.substring(0, offset),
+        part_2 = this.orginal_text.substring(offset+old_value.length),
+        add_2_offset = new_value.length - old_value.length;
+
     this.orginal_text = part_1 + new_value + part_2;
-    this.setValue(this.text_area, this.orginal_text);
-    var add_2_offset = new_value.length - old_value.length;
-    for(var j=0; j < this.results.length; j++) {
-        //Don't edit the offset of the current item
-        if(j != id && j > id){
+    $(this.text_area).val(this.orginal_text);
+    for (var j=0, len=this.results.length; j<len; j++) {
+        // Don't edit the offset of the current item
+        if (j != id && j > id)
             this.results[j]['attrs']['o'] += add_2_offset;
-        }
     }
-}
+};
 
-GoogieSpell.prototype.saveOldValue = function(elm, old_value) {
+this.saveOldValue = function(elm, old_value) {
     elm.is_changed = true;
     elm.old_value = old_value;
-}
+};
 
-GoogieSpell.prototype.createListSeparator = function() {
-    var e_col = AJS.TD(" ");
-    e_col.googie_action_btn = "1";
-    e_col.style.cursor = "default";
-    e_col.style.fontSize = "3px";
-    e_col.style.borderTop = "1px solid #ccc";
-    e_col.style.paddingTop = "3px";
+this.createListSeparator = function()
+{
+    var td = document.createElement('td'),
+        tr = document.createElement('tr');
 
-    return AJS.TR(e_col);
-}
+    $(td).html(' ').attr('googie_action_btn', '1')
+        .css({'cursor': 'default', 'font-size': '3px', 'border-top': '1px solid #ccc', 'padding-top': '3px'});
+    tr.appendChild(td);
 
-GoogieSpell.prototype.correctError = function(id, elm, l_elm, /*optional*/ rm_pre_space) {
-    var old_value = elm.innerHTML;
-    var new_value = l_elm.innerHTML;
-    var offset = this.results[id]['attrs']['o'];
+    return tr;
+};
 
-    if(rm_pre_space) {
+this.correctError = function(id, elm, l_elm, rm_pre_space)
+{
+    var old_value = elm.innerHTML,
+        new_value = l_elm.nodeType == 3 ? l_elm.nodeValue : l_elm.innerHTML,
+        offset = this.results[id]['attrs']['o'];
+
+    if (rm_pre_space) {
         var pre_length = elm.previousSibling.innerHTML;
         elm.previousSibling.innerHTML = pre_length.slice(0, pre_length.length-1);
         old_value = " " + old_value;
@@ -1856,698 +450,703 @@
     }
 
     this.hideErrorWindow();
-
     this.updateOrginalText(offset, old_value, new_value, id);
 
-    elm.innerHTML = new_value;
-    
-    elm.style.color = "green";
-    elm.is_corrected = true;
+    $(elm).html(new_value).css('color', 'green').attr('is_corrected', true);
 
     this.results[id]['attrs']['l'] = new_value.length;
 
-    if(!AJS.isDefined(elm.old_value))
+    if (!this.isDefined(elm.old_value))
         this.saveOldValue(elm, old_value);
-    
+
     this.errorFixed();
-}
+};
 
-GoogieSpell.prototype.showErrorWindow = function(elm, id) {
-    if(this.show_menu_observer)
+this.ignoreError = function(elm, id)
+{
+    // @TODO: ignore all same words
+    $(elm).removeAttr('class').css('color', '').off();
+    this.hideErrorWindow();
+};
+
+this.showErrorWindow = function(elm, id)
+{
+    if (this.show_menu_observer)
         this.show_menu_observer(this);
-    var me = this;
 
-    var abs_pos = AJS.absolutePosition(elm);
-    abs_pos.y -= this.edit_layer.scrollTop;
-    this.error_window.style.visibility = "visible";
+    var ref = this,
+        pos = $(elm).offset(),
+        table = document.createElement('table'),
+        list = document.createElement('tbody');
 
-    AJS.setTop(this.error_window, (abs_pos.y+20));
-    AJS.setLeft(this.error_window, (abs_pos.x));
+    $(this.error_window).html('');
+    $(table).addClass('googie_list').attr('googie_action_btn', '1');
 
-    this.error_window.innerHTML = "";
-
-    var table = AJS.TABLE({'class': 'googie_list'});
-    table.googie_action_btn = "1";
-    var list = AJS.TBODY();
-
-    //Check if we should use custom menu builder, if not we use the default
+    // Check if we should use custom menu builder, if not we use the default
     var changed = false;
-    if(this.custom_menu_builder != []) {
-        for(var k=0; k<this.custom_menu_builder.length; k++) {
-            var eb = this.custom_menu_builder[k];
-            if(eb[0]((this.results[id]))){
-                changed = eb[1](this, list, elm);
-                break;
-            }
+    for (var k=0; k<this.custom_menu_builder.length; k++) {
+        var eb = this.custom_menu_builder[k];
+        if (eb[0](this.results[id])) {
+            changed = eb[1](this, list, elm);
+            break;
         }
     }
-    if(!changed) {
-        //Build up the result list
-        var suggestions = this.results[id]['suggestions'];
-        var offset = this.results[id]['attrs']['o'];
-        var len = this.results[id]['attrs']['l'];
 
-        if(suggestions.length == 0) {
-            var row = AJS.TR();
-            var item = AJS.TD({'style': 'cursor: default;'});
-            var dummy = AJS.SPAN();
-            dummy.innerHTML = this.lang_no_suggestions;
-            AJS.ACN(item, AJS.TN(dummy.innerHTML));
-            item.googie_action_btn = "1";
+    if (!changed) {
+        // Build up the result list
+        var suggestions = this.results[id]['suggestions'],
+            offset = this.results[id]['attrs']['o'],
+            len = this.results[id]['attrs']['l'],
+            row, item, dummy;
+
+        // [Add to dictionary] button
+        if (this.has_dictionary && !$(elm).attr('is_corrected')) {
+            row = document.createElement('tr'),
+            item = document.createElement('td'),
+            dummy = document.createElement('span');
+
+            $(dummy).text(this.lang_learn_word);
+            $(item).attr('googie_action_btn', '1').css('cursor', 'default')
+                .mouseover(ref.item_onmouseover)
+                .mouseout(ref.item_onmouseout)
+                .click(function(e) {
+                    ref.learnWord(elm, id);
+                    ref.ignoreError(elm, id);
+                });
+
+            item.appendChild(dummy);
+            row.appendChild(item);
+            list.appendChild(row);
+        }
+/*
+        if (suggestions.length == 0) {
+            row = document.createElement('tr'),
+            item = document.createElement('td'),
+            dummy = document.createElement('span');
+
+            $(dummy).text(this.lang_no_suggestions);
+            $(item).attr('googie_action_btn', '1').css('cursor', 'default');
+
+            item.appendChild(dummy);
+            row.appendChild(item);
+            list.appendChild(row);
+        }
+*/
+        for (var i=0, len=suggestions.length; i < len; i++) {
+            row = document.createElement('tr'),
+            item = document.createElement('td'),
+            dummy = document.createElement('span');
+
+            $(dummy).html(suggestions[i]);
+
+            $(item).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout)
+              .click(function(e) { ref.correctError(id, elm, e.target.firstChild) });
+
+            item.appendChild(dummy);
             row.appendChild(item);
             list.appendChild(row);
         }
 
-        for(i=0; i < suggestions.length; i++) {
-            var row = AJS.TR();
-            var item = AJS.TD();
-            var dummy = AJS.SPAN();
-            dummy.innerHTML = suggestions[i];
-            item.appendChild(AJS.TN(dummy.innerHTML));
-            
-            var fn = function(e) {
-                var l_elm = AJS.getEventElm(e);
-                this.correctError(id, elm, l_elm);
-            };
+        // The element is changed, append the revert
+        if (elm.is_changed && elm.innerHTML != elm.old_value) {
+            var old_value = elm.old_value,
+                revert_row = document.createElement('tr'),
+                revert = document.createElement('td'),
+                rev_span = document.createElement('span');
 
-            AJS.AEV(item, "click", AJS.$b(fn, this));
+            $(rev_span).addClass('googie_list_revert').html(this.lang_revert + ' ' + old_value);
 
-            item.onmouseover = GoogieSpell.item_onmouseover;
-            item.onmouseout = GoogieSpell.item_onmouseout;
-            row.appendChild(item);
-            list.appendChild(row);
-        }
+            $(revert).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout)
+                .click(function(e) {
+                    ref.updateOrginalText(offset, elm.innerHTML, old_value, id);
+                    $(elm).removeAttr('is_corrected').css('color', '#b91414').html(old_value);
+                    ref.hideErrorWindow();
+                });
 
-        //The element is changed, append the revert
-        if(elm.is_changed && elm.innerHTML != elm.old_value) {
-            var old_value = elm.old_value;
-            var revert_row = AJS.TR();
-            var revert = AJS.TD();
-
-            revert.onmouseover = GoogieSpell.item_onmouseover;
-            revert.onmouseout = GoogieSpell.item_onmouseout;
-            var rev_span = AJS.SPAN({'class': 'googie_list_revert'});
-            rev_span.innerHTML = this.lang_revert + " " + old_value;
             revert.appendChild(rev_span);
-
-            var fn = function(e) { 
-                this.updateOrginalText(offset, elm.innerHTML, old_value, id);
-                elm.is_corrected = true;
-                elm.style.color = "#b91414";
-                elm.innerHTML = old_value;
-                this.hideErrorWindow();
-            };
-            AJS.AEV(revert, "click", AJS.$b(fn, this));
-
             revert_row.appendChild(revert);
             list.appendChild(revert_row);
         }
-        
-        //Append the edit box
-        var edit_row = AJS.TR();
-        var edit = AJS.TD({'style': 'cursor: default'});
 
-        var edit_input = AJS.INPUT({'style': 'width: 120px; margin:0; padding:0', 'value': elm.innerHTML});
-        edit_input.googie_action_btn = "1";
+        // Append the edit box
+        var edit_row = document.createElement('tr'),
+            edit = document.createElement('td'),
+            edit_input = document.createElement('input'),
+            ok_pic = document.createElement('img'),
+            edit_form = document.createElement('form');
 
         var onsub = function () {
-            if(edit_input.value != "") {
-                if(!AJS.isDefined(elm.old_value))
-                    this.saveOldValue(elm, elm.innerHTML);
+            if (edit_input.value != '') {
+                if (!ref.isDefined(elm.old_value))
+                    ref.saveOldValue(elm, elm.innerHTML);
 
-                this.updateOrginalText(offset, elm.innerHTML, edit_input.value, id);
-                elm.style.color = "green"
-                elm.is_corrected = true;
-                elm.innerHTML = edit_input.value;
-                
-                this.hideErrorWindow();
+                ref.updateOrginalText(offset, elm.innerHTML, edit_input.value, id);
+                $(elm).attr('is_corrected', true).css('color', 'green').text(edit_input.value);
+                ref.hideErrorWindow();
             }
             return false;
         };
-        onsub = AJS.$b(onsub, this);
-        
-        var ok_pic = AJS.IMG({'src': this.img_dir + "ok.gif", 'style': 'width: 32px; height: 16px; margin-left: 2px; margin-right: 2px; cursor: pointer;'});
-        var edit_form = AJS.FORM({'style': 'margin: 0; padding: 0; cursor: default;'}, edit_input, ok_pic);
 
-        edit_form.googie_action_btn = "1";
-        edit.googie_action_btn = "1";
+        $(edit_input).width(120)
+          .css({'margin': 0, 'padding': 0})
+          .val($(elm).text()).attr('googie_action_btn', '1');
+        $(edit).css('cursor', 'default').attr('googie_action_btn', '1');
 
-        AJS.AEV(edit_form, "submit", onsub);
-        AJS.AEV(ok_pic, "click", onsub);
-        
+        $(ok_pic).attr('src', this.img_dir + 'ok.gif')
+            .width(32).height(16)
+            .css({'cursor': 'pointer', 'margin-left': '2px', 'margin-right': '2px'})
+            .click(onsub);
+
+        $(edit_form).attr('googie_action_btn', '1')
+            .css({'margin': 0, 'padding': 0, 'cursor': 'default', 'white-space': 'nowrap'})
+            .submit(onsub);
+
+        edit_form.appendChild(edit_input);
+        edit_form.appendChild(ok_pic);
         edit.appendChild(edit_form);
         edit_row.appendChild(edit);
         list.appendChild(edit_row);
 
-        //Append extra menu items
-        if(this.extra_menu_items.length > 0)
-            AJS.ACN(list, this.createListSeparator());
+        // Append extra menu items
+        if (this.extra_menu_items.length > 0)
+            list.appendChild(this.createListSeparator());
 
         var loop = function(i) {
-                if(i < me.extra_menu_items.length) {
-                    var e_elm = me.extra_menu_items[i];
+            if (i < ref.extra_menu_items.length) {
+                var e_elm = ref.extra_menu_items[i];
 
-                    if(!e_elm[2] || e_elm[2](elm, me)) {
-                        var e_row = AJS.TR();
-                        var e_col = AJS.TD(e_elm[0]);
+                if (!e_elm[2] || e_elm[2](elm, ref)) {
+                    var e_row = document.createElement('tr'),
+                      e_col = document.createElement('td');
 
-                        e_col.onmouseover = GoogieSpell.item_onmouseover;
-                        e_col.onmouseout = GoogieSpell.item_onmouseout;
+                    $(e_col).html(e_elm[0])
+                        .mouseover(ref.item_onmouseover)
+                        .mouseout(ref.item_onmouseout)
+                        .click(function() { return e_elm[1](elm, ref) });
 
-                        var fn = function() {
-                            return e_elm[1](elm, me);
-                        };
-                        AJS.AEV(e_col, "click", fn);
-
-                        AJS.ACN(e_row, e_col);
-                        AJS.ACN(list, e_row);
-
-                    }
-                    loop(i+1);
+                    e_row.appendChild(e_col);
+                    list.appendChild(e_row);
                 }
-        }
+                loop(i+1);
+            }
+        };
+
         loop(0);
         loop = null;
 
         //Close button
-        if(this.use_close_btn) {
-            AJS.ACN(list, this.createCloseButton(this.hideErrorWindow));
+        if (this.use_close_btn) {
+            list.appendChild(this.createCloseButton(this.hideErrorWindow));
         }
     }
 
     table.appendChild(list);
     this.error_window.appendChild(table);
 
-    //Dummy for IE - dropdown bug fix
-    if(AJS.isIe() && !this.error_window_iframe) {
-        var iframe = AJS.IFRAME({'style': 'position: absolute; z-index: 0;'});
-        AJS.ACN(AJS.getBody(), iframe);
-        this.error_window_iframe = iframe;
+    // calculate and set position
+    var height = $(this.error_window).height(),
+        width = $(this.error_window).width(),
+        pageheight = $(document).height(),
+        pagewidth = $(document).width(),
+        top = pos.top + height + 20 < pageheight ? pos.top + 20 : pos.top - height,
+        left = pos.left + width < pagewidth ? pos.left : pos.left - width;
+
+    $(this.error_window).css({'top': top+'px', 'left': left+'px'}).show();
+
+    // Dummy for IE - dropdown bug fix
+    if (document.all && !window.opera) {
+        if (!this.error_window_iframe) {
+            var iframe = $('<iframe>').css({'position': 'absolute', 'z-index': -1});
+            $('body').append(iframe);
+            this.error_window_iframe = iframe;
+        }
+
+        $(this.error_window_iframe)
+            .css({'top': this.error_window.offsetTop, 'left': this.error_window.offsetLeft,
+                'width': this.error_window.offsetWidth, 'height': this.error_window.offsetHeight})
+            .show();
     }
-    if(AJS.isIe()) {
-        var iframe = this.error_window_iframe;
-        AJS.setTop(iframe, this.error_window.offsetTop);
-        AJS.setLeft(iframe, this.error_window.offsetLeft);
-
-        AJS.setWidth(iframe, this.error_window.offsetWidth);
-        AJS.setHeight(iframe, this.error_window.offsetHeight);
-
-        iframe.style.visibility = "visible";
-    }
-
-    //Set focus on the last element
-    var link = this.createFocusLink('link');
-    list.appendChild(AJS.TR(AJS.TD({'style': 'text-align: right; font-size: 1px; height: 1px; margin: 0; padding: 0;'}, link)));
-    link.focus();
-}
+};
 
 
 //////
 // Edit layer (the layer where the suggestions are stored)
 //////
-GoogieSpell.prototype.createEditLayer = function(width, height) {
-    this.edit_layer = AJS.DIV({'class': 'googie_edit_layer'});
+this.createEditLayer = function(width, height)
+{
+    this.edit_layer = document.createElement('div');
+    $(this.edit_layer).addClass('googie_edit_layer').attr('id', 'googie_edit_layer')
+        .width(width).height(height);
 
-    //Set the style so it looks like edit areas
-    this.edit_layer.className = this.text_area.className;
-    this.edit_layer.style.border = "1px solid #999";
-    this.edit_layer.style.backgroundColor = "#F1EDFE";  // modified by roundcube
-    this.edit_layer.style.padding = "3px";
-    this.edit_layer.style.margin = "0px";
-
-    AJS.setWidth(this.edit_layer, (width-8));
-
-    if(AJS.nodeName(this.text_area) != "input" || this.getValue(this.text_area) == "") {
-        this.edit_layer.style.overflow = "auto";
-        AJS.setHeight(this.edit_layer, (height-6));
-    }
-    else {
-        this.edit_layer.style.overflow = "hidden";
+    if (this.text_area.nodeName.toLowerCase() != 'input' || $(this.text_area).val() == '') {
+        $(this.edit_layer).css('overflow', 'auto');
+    } else {
+        $(this.edit_layer).css('overflow', 'hidden');
     }
 
-    if(this.edit_layer_dbl_click) {
-        var me = this;
-        var fn = function(e) {
-            if(AJS.getEventElm(e).className != "googie_link" && !me.isErrorWindowShown()) {
-                me.resumeEditing();
+    var ref = this;
+
+    if (this.edit_layer_dbl_click) {
+        $(this.edit_layer).dblclick(function(e) {
+            if (e.target.className != 'googie_link' && !ref.isErrorWindowShown()) {
+                ref.resumeEditing();
                 var fn1 = function() {
-                    me.text_area.focus();
+                    $(ref.text_area).focus();
                     fn1 = null;
                 };
-                AJS.callLater(fn1, 10);
+                window.setTimeout(fn1, 10);
             }
             return false;
-        };
-        this.edit_layer.ondblclick = fn;
-        fn = null;
+        });
     }
-}
+};
 
-GoogieSpell.prototype.resumeEditing = function() {
-    this.setStateChanged("spell_check");
-    this.switch_lan_pic.style.display = "inline";
+this.resumeEditing = function()
+{
+    this.setStateChanged('ready');
 
-    if(this.edit_layer)
+    if (this.edit_layer)
         this.el_scroll_top = this.edit_layer.scrollTop;
 
     this.hideErrorWindow();
 
-    if(this.main_controller)
-        this.spell_span.className = "googie_no_style";
+    if (this.main_controller)
+        $(this.spell_span).removeClass().addClass('googie_no_style');
 
-    if(!this.ignore) {
-        //Remove the EDIT_LAYER
-        try {
-            this.edit_layer.parentNode.removeChild(this.edit_layer);
-            if(this.use_focus) {
-                AJS.removeElement(this.focus_link_t);
-                AJS.removeElement(this.focus_link_b);
-            }
-        }
-        catch(e) {
+    if (!this.ignore) {
+        if (this.use_focus) {
+            $(this.focus_link_t).remove();
+            $(this.focus_link_b).remove();
         }
 
-        AJS.showElement(this.text_area);
+        $(this.edit_layer).remove();
+        $(this.text_area).show();
 
-        if(this.el_scroll_top != undefined)
+        if (this.el_scroll_top != undefined)
             this.text_area.scrollTop = this.el_scroll_top;
     }
-
     this.checkSpellingState(false);
-}
+};
 
-GoogieSpell.prototype.createErrorLink = function(text, id) {
-    var elm = AJS.SPAN({'class': 'googie_link'});
-    var me = this;
-    var d = function (e) {
-        me.showErrorWindow(elm, id);
-        d = null;
-        return false;
-    };
-    AJS.AEV(elm, "click", d);
+this.createErrorLink = function(text, id)
+{
+    var elm = document.createElement('span'),
+        ref = this,
+        d = function (e) {
+            ref.showErrorWindow(elm, id);
+            d = null;
+            return false;
+        };
 
-    elm.googie_action_btn = "1";
-    elm.g_id = id;
-    elm.is_corrected = false;
-    elm.oncontextmenu = d;
-    elm.innerHTML = text;
+    $(elm).html(text).addClass('googie_link').click(d).removeAttr('is_corrected')
+        .attr({'googie_action_btn' : '1', 'g_id' : id});
+
     return elm;
-}
+};
 
-GoogieSpell.createPart = function(txt_part) {
-    if(txt_part == " ")
-        return AJS.TN(" ");
-    var result = AJS.SPAN();
+this.createPart = function(txt_part)
+{
+    if (txt_part == " ")
+        return document.createTextNode(" ");
 
-    var is_first = true;
-    var is_safari = (navigator.userAgent.toLowerCase().indexOf("safari") != -1);
-
-    var part = AJS.SPAN();
-    txt_part = GoogieSpell.escapeSepcial(txt_part);
+    txt_part = this.escapeSpecial(txt_part);
     txt_part = txt_part.replace(/\n/g, "<br>");
     txt_part = txt_part.replace(/    /g, " &nbsp;");
     txt_part = txt_part.replace(/^ /g, "&nbsp;");
     txt_part = txt_part.replace(/ $/g, "&nbsp;");
-    
-    part.innerHTML = txt_part;
 
-    return part;
-}
+    var span = document.createElement('span');
+    $(span).html(txt_part);
+    return span;
+};
 
-GoogieSpell.prototype.showErrorsInIframe = function() {
-    var output = AJS.DIV();
-    output.style.textAlign = "left";
-    var pointer = 0;
-    var results = this.results;
+this.showErrorsInIframe = function()
+{
+    var output = document.createElement('div'),
+        pointer = 0,
+        results = this.results;
 
-    if(results.length > 0) {
-        for(var i=0; i < results.length; i++) {
-            var offset = results[i]['attrs']['o'];
-            var len = results[i]['attrs']['l'];
-            
-            var part_1_text = this.orginal_text.substring(pointer, offset);
-            var part_1 = GoogieSpell.createPart(part_1_text);
+    if (results.length > 0) {
+        for (var i=0, length=results.length; i < length; i++) {
+            var offset = results[i]['attrs']['o'],
+                len = results[i]['attrs']['l'],
+                part_1_text = this.orginal_text.substring(pointer, offset),
+                part_1 = this.createPart(part_1_text);
+
             output.appendChild(part_1);
             pointer += offset - pointer;
-            
-            //If the last child was an error, then insert some space
+
+            // If the last child was an error, then insert some space
             var err_link = this.createErrorLink(this.orginal_text.substr(offset, len), i);
             this.error_links.push(err_link);
             output.appendChild(err_link);
             pointer += len;
         }
-        //Insert the rest of the orginal text
-        var part_2_text = this.orginal_text.substr(pointer, this.orginal_text.length);
 
-        var part_2 = GoogieSpell.createPart(part_2_text);
+        // Insert the rest of the orginal text
+        var part_2_text = this.orginal_text.substr(pointer, this.orginal_text.length),
+            part_2 = this.createPart(part_2_text);
+
         output.appendChild(part_2);
     }
     else
         output.innerHTML = this.orginal_text;
 
+    $(output).css('text-align', 'left');
+
     var me = this;
-    if(this.custom_item_evaulator)
-        AJS.map(this.error_links, function(elm){me.custom_item_evaulator(me, elm)});
-    
-    AJS.ACN(this.edit_layer, output);
+    if (this.custom_item_evaulator)
+        $.map(this.error_links, function(elm){me.custom_item_evaulator(me, elm)});
 
-    //Hide text area
-    this.text_area_bottom = this.text_area.offsetTop + this.text_area.offsetHeight;
+    $(this.edit_layer).append(output);
 
-    AJS.hideElement(this.text_area);
+    // Hide text area and show edit layer
+    $(this.text_area).hide();
+    $(this.edit_layer).insertBefore(this.text_area);
 
-    AJS.insertBefore(this.edit_layer, this.text_area);
-
-    if(this.use_focus) {
+    if (this.use_focus) {
         this.focus_link_t = this.createFocusLink('focus_t');
         this.focus_link_b = this.createFocusLink('focus_b');
 
-        AJS.insertBefore(this.focus_link_t, this.edit_layer);
-        AJS.insertAfter(this.focus_link_b, this.edit_layer);
+        $(this.focus_link_t).insertBefore(this.edit_layer);
+        $(this.focus_link_b).insertAfter(this.edit_layer);
     }
 
-    this.edit_layer.scrollTop = this.ta_scroll_top;
-}
+//    this.edit_layer.scrollTop = this.ta_scroll_top;
+};
 
 
 //////
 // Choose language menu
 //////
-GoogieSpell.prototype.createLangWindow = function() {
-    this.language_window = AJS.DIV({'class': 'googie_window'});
-    AJS.setWidth(this.language_window, 100);
+this.createLangWindow = function()
+{
+    this.language_window = document.createElement('div');
+    $(this.language_window).addClass('googie_window popupmenu')
+        .width(100).attr('googie_action_btn', '1');
 
-    this.language_window.googie_action_btn = "1";
+    // Build up the result list
+    var table = document.createElement('table'),
+        list = document.createElement('tbody'),
+        ref = this,
+        row, item, span;
 
-    //Build up the result list
-    var table = AJS.TABLE({'class': 'googie_list'});
-    AJS.setWidth(table, "100%");
-    var list = AJS.TBODY();
+    $(table).addClass('googie_list').width('100%');
+    this.lang_elms = [];
 
-    this.lang_elms = new Array();
+    for (i=0; i < this.langlist_codes.length; i++) {
+        row = document.createElement('tr');
+        item = document.createElement('td');
+        span = document.createElement('span');
 
-    for(i=0; i < this.langlist_codes.length; i++) {
-        var row = AJS.TR();
-        var item = AJS.TD();
-        item.googieId = this.langlist_codes[i];
+        $(span).text(this.lang_to_word[this.langlist_codes[i]]);
         this.lang_elms.push(item);
-        var lang_span = AJS.SPAN();
-        lang_span.innerHTML = this.lang_to_word[this.langlist_codes[i]];
-        item.appendChild(AJS.TN(lang_span.innerHTML));
 
-        var fn = function(e) {
-            var elm = AJS.getEventElm(e);
-            this.deHighlightCurSel();
+        $(item).attr('googieId', this.langlist_codes[i])
+            .click(function(e) {
+                ref.deHighlightCurSel();
+                ref.setCurrentLanguage($(this).attr('googieId'));
 
-            this.setCurrentLanguage(elm.googieId);
+                if (ref.lang_state_observer != null) {
+                    ref.lang_state_observer();
+                }
 
-            if(this.lang_state_observer != null) {
-                this.lang_state_observer();
-            }
+                ref.highlightCurSel();
+                ref.hideLangWindow();
+            })
+            .mouseover(function(e) {
+                if (this.className != "googie_list_selected")
+                    this.className = "googie_list_onhover";
+            })
+            .mouseout(function(e) {
+                if (this.className != "googie_list_selected")
+                    this.className = "googie_list_onout";
+            });
 
-            this.highlightCurSel();
-            this.hideLangWindow();
-        };
-        AJS.AEV(item, "click", AJS.$b(fn, this));
-
-        item.onmouseover = function(e) { 
-            var i_it = AJS.getEventElm(e);
-            if(i_it.className != "googie_list_selected")
-                i_it.className = "googie_list_onhover";
-        };
-        item.onmouseout = function(e) { 
-            var i_it = AJS.getEventElm(e);
-            if(i_it.className != "googie_list_selected")
-                i_it.className = "googie_list_onout"; 
-        };
-
+        item.appendChild(span);
         row.appendChild(item);
         list.appendChild(row);
     }
 
-    //Close button
-    if(this.use_close_btn) {
-        list.appendChild(this.createCloseButton(this.hideLangWindow));
+    // Close button
+    if (this.use_close_btn) {
+        list.appendChild(this.createCloseButton(function () { ref.hideLangWindow.apply(ref) }));
     }
 
     this.highlightCurSel();
 
     table.appendChild(list);
     this.language_window.appendChild(table);
-}
+};
 
-GoogieSpell.prototype.setCurrentLanguage = function(lan_code) {
-    GOOGIE_CUR_LANG = lan_code;
+this.isLangWindowShown = function()
+{
+    return $(this.language_window).is(':visible');
+};
 
-    //Set cookie
-    var now = new Date();
-    now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
-    setCookie('language', lan_code, now);
-}
+this.hideLangWindow = function()
+{
+    $(this.language_window).hide();
+    $(this.switch_lan_pic).removeClass().addClass('googie_lang_3d_on');
+};
 
-GoogieSpell.prototype.isLangWindowShown = function() {
-    return this.language_window != null && this.language_window.style.visibility == "visible";
-}
+this.showLangWindow = function(elm)
+{
+    if (this.show_menu_observer)
+        this.show_menu_observer(this);
 
-GoogieSpell.prototype.hideLangWindow = function() {
-    try {
-        this.language_window.style.visibility = "hidden";
-        this.switch_lan_pic.className = "googie_lang_3d_on";
-    }
-    catch(e) {}
-}
+    this.createLangWindow();
+    $('body').append(this.language_window);
 
-GoogieSpell.prototype.deHighlightCurSel = function() {
-    this.lang_cur_elm.className = "googie_list_onout";
-}
+    var pos = $(elm).offset(),
+        height = $(elm).height(),
+        width = $(elm).width(),
+        h = $(this.language_window).height(),
+        pageheight = $(document).height(),
+        left = this.change_lang_pic_placement == 'right' ?
+            pos.left - 100 + width : pos.left + width,
+        top = pos.top + h < pageheight ? pos.top + height : pos.top - h - 4;
 
-GoogieSpell.prototype.highlightCurSel = function() {
-    if(GOOGIE_CUR_LANG == null)
+    $(this.language_window).css({'top' : top+'px','left' : left+'px'}).show();
+
+    this.highlightCurSel();
+};
+
+this.deHighlightCurSel = function()
+{
+    $(this.lang_cur_elm).removeClass().addClass('googie_list_onout');
+};
+
+this.highlightCurSel = function()
+{
+    if (GOOGIE_CUR_LANG == null)
         GOOGIE_CUR_LANG = GOOGIE_DEFAULT_LANG;
-    for(var i=0; i < this.lang_elms.length; i++) {
-        if(this.lang_elms[i].googieId == GOOGIE_CUR_LANG) {
-            this.lang_elms[i].className = "googie_list_selected";
+    for (var i=0; i < this.lang_elms.length; i++) {
+        if ($(this.lang_elms[i]).attr('googieId') == GOOGIE_CUR_LANG) {
+            this.lang_elms[i].className = 'googie_list_selected';
             this.lang_cur_elm = this.lang_elms[i];
         }
         else {
-            this.lang_elms[i].className = "googie_list_onout";
+            this.lang_elms[i].className = 'googie_list_onout';
         }
     }
-}
+};
 
-GoogieSpell.prototype.showLangWindow = function(elm, ofst_top, ofst_left) {
-    if(this.show_menu_observer)
-        this.show_menu_observer(this);
-    if(!AJS.isDefined(ofst_top))
-        ofst_top = 18;  // modified by roundcube
-    if(!AJS.isDefined(ofst_left))
-        ofst_left = 22; // modified by roundcube
+this.createChangeLangPic = function()
+{
+    var img = $('<img>')
+        .attr({src: this.img_dir + 'change_lang.gif', 'alt': 'Change language', 'googie_action_btn': '1'}),
+        switch_lan = document.createElement('span');
+        ref = this;
 
-    this.createLangWindow();
-    AJS.getBody().appendChild(this.language_window);
+    $(switch_lan).addClass('googie_lang_3d_on')
+        .append(img)
+        .click(function(e) {
+            var elm = this.tagName.toLowerCase() == 'img' ? this.parentNode : this;
+            if($(elm).hasClass('googie_lang_3d_click')) {
+                elm.className = 'googie_lang_3d_on';
+                ref.hideLangWindow();
+            }
+            else {
+                elm.className = 'googie_lang_3d_click';
+                ref.showLangWindow(elm);
+            }
+        });
 
-    var abs_pos = AJS.absolutePosition(elm);
-    AJS.showElement(this.language_window);
-    AJS.setTop(this.language_window, (abs_pos.y+ofst_top));
-    AJS.setLeft(this.language_window, (abs_pos.x+ofst_left-this.language_window.offsetWidth));
-
-    this.highlightCurSel();
-    this.language_window.style.visibility = "visible";
-}
-
-GoogieSpell.prototype.createChangeLangPic = function() {
-    var img = AJS.IMG({'src': this.img_dir + 'change_lang.gif', 'alt': "Change language"});
-    img.googie_action_btn = "1";
-    var switch_lan = AJS.SPAN({'class': 'googie_lang_3d_on', 'style': 'padding-left: 6px;'}, img);
-
-    var fn = function(e) {
-        var elm = AJS.getEventElm(e);
-        if(AJS.nodeName(elm) == 'img')
-            elm = elm.parentNode;
-        if(elm.className == "googie_lang_3d_click") {
-            elm.className = "googie_lang_3d_on";
-            this.hideLangWindow();
-        }
-        else {
-            elm.className = "googie_lang_3d_click";
-            this.showLangWindow(switch_lan);
-        }
-    }
-
-    AJS.AEV(switch_lan, "click", AJS.$b(fn, this));
     return switch_lan;
-}
+};
 
-GoogieSpell.prototype.createSpellDiv = function() {
-    var chk_spell = AJS.SPAN({'class': 'googie_check_spelling_link'});
+this.createSpellDiv = function()
+{
+    var span = document.createElement('span');
 
-    chk_spell.innerHTML = this.lang_chck_spell;
-    var spell_img = null;
-    if(this.show_spell_img)
-        spell_img = AJS.IMG({'src': this.img_dir + "spellc.gif"});
-    return AJS.SPAN(spell_img, " ", chk_spell);
-}
+    $(span).addClass('googie_check_spelling_link').text(this.lang_chck_spell);
+
+    if (this.show_spell_img) {
+        $(span).append(' ').append($('<img>').attr('src', this.img_dir + 'spellc.gif'));
+    }
+    return span;
+};
 
 
 //////
 // State functions
 /////
-GoogieSpell.prototype.flashNoSpellingErrorState = function(on_finish) {
-    var no_spell_errors;
+this.flashNoSpellingErrorState = function(on_finish)
+{
+    this.setStateChanged('no_error_found');
 
-    if(on_finish) {
-        var fn = function() {
-            on_finish();
-            this.checkSpellingState();
-        };
-        no_spell_errors = fn;
+    var ref = this;
+    if (this.main_controller) {
+        var no_spell_errors;
+        if (on_finish) {
+            var fn = function() {
+                on_finish();
+                ref.checkSpellingState();
+            };
+            no_spell_errors = fn;
+        }
+        else
+            no_spell_errors = function () { ref.checkSpellingState() };
+
+        var rsm = $('<span>').text(this.lang_no_error_found);
+
+        $(this.switch_lan_pic).hide();
+        $(this.spell_span).empty().append(rsm)
+        .removeClass().addClass('googie_check_spelling_ok');
+
+        window.setTimeout(no_spell_errors, 1000);
     }
-    else
-        no_spell_errors = this.checkSpellingState;
+};
 
-    this.setStateChanged("no_error_found");
-
-    if(this.main_controller) {
-        AJS.hideElement(this.switch_lan_pic);
-
-        var dummy = AJS.IMG({'src': this.img_dir + "blank.gif", 'style': 'height: 16px; width: 1px;'});
-        var rsm = AJS.SPAN();
-        rsm.innerHTML = this.lang_no_error_found;
-
-        AJS.RCN(this.spell_span, AJS.SPAN(dummy, rsm));
-
-        this.spell_span.className = "googie_check_spelling_ok";
-        this.spell_span.style.textDecoration = "none";
-        this.spell_span.style.cursor = "default";
-
-        AJS.callLater(AJS.$b(no_spell_errors, this), 1200, [false]);
-    }
-}
-
-GoogieSpell.prototype.resumeEditingState = function() {
-    this.setStateChanged("resume_editing");
+this.resumeEditingState = function()
+{
+    this.setStateChanged('resume_editing');
 
     //Change link text to resume
-    if(this.main_controller) {
-        AJS.hideElement(this.switch_lan_pic);
-        var dummy = AJS.IMG({'src': this.img_dir + "blank.gif", 'style': 'height: 16px; width: 1px;'});
-        var rsm = AJS.SPAN();
-        rsm.innerHTML = this.lang_rsm_edt;
-        AJS.RCN(this.spell_span, AJS.SPAN(dummy, rsm));
-    
-        var fn = function(e) {
-            this.resumeEditing();
-        }
-        this.spell_span.onclick = AJS.$b(fn, this);
+    if (this.main_controller) {
+        var rsm = $('<span>').text(this.lang_rsm_edt);
+    var ref = this;
 
-        this.spell_span.className = "googie_resume_editing";
+        $(this.switch_lan_pic).hide();
+        $(this.spell_span).empty().off().append(rsm)
+            .click(function() { ref.resumeEditing(); })
+            .removeClass().addClass('googie_resume_editing');
     }
 
     try { this.edit_layer.scrollTop = this.ta_scroll_top; }
-    catch(e) { }
-}
+    catch (e) {};
+};
 
-GoogieSpell.prototype.checkSpellingState = function(fire) {
-    if(!AJS.isDefined(fire) || fire)
-        this.setStateChanged("spell_check");
+this.checkSpellingState = function(fire)
+{
+    if (fire)
+        this.setStateChanged('ready');
 
-    if(this.show_change_lang_pic)
+    if (this.show_change_lang_pic)
         this.switch_lan_pic = this.createChangeLangPic();
     else
-        this.switch_lan_pic = AJS.SPAN();
+        this.switch_lan_pic = document.createElement('span');
 
-    var span_chck = this.createSpellDiv();
-    var fn = function() {
-        this.spellCheck();
-    };
+    var span_chck = this.createSpellDiv(),
+        ref = this;
 
-    if(this.custom_spellcheck_starter)
-        span_chck.onclick = this.custom_spellcheck_starter;
+    if (this.custom_spellcheck_starter)
+        $(span_chck).click(function(e) { ref.custom_spellcheck_starter(); });
     else {
-        span_chck.onclick = AJS.$b(fn, this);
+        $(span_chck).click(function(e) { ref.spellCheck(); });
+    }
+
+    if (this.main_controller) {
+        if (this.change_lang_pic_placement == 'left') {
+            $(this.spell_container).empty().append(this.switch_lan_pic).append(' ').append(span_chck);
+        } else {
+            $(this.spell_container).empty().append(span_chck).append(' ').append(this.switch_lan_pic);
+        }
     }
 
     this.spell_span = span_chck;
-    if(this.main_controller) {
-        if(this.change_lang_pic_placement == "left")
-            AJS.RCN(this.spell_container, span_chck, " ", this.switch_lan_pic);
-        else
-            AJS.RCN(this.spell_container, this.switch_lan_pic, " ", span_chck);
-    }
-    // modified by roundcube
-    this.check_link = span_chck;
-}
+};
 
 
 //////
 // Misc. functions
 /////
-GoogieSpell.item_onmouseover = function(e) {
-    var elm = AJS.getEventElm(e);
-    if(elm.className != "googie_list_revert" && elm.className != "googie_list_close")
-        elm.className = "googie_list_onhover";
-    else
-        elm.parentNode.className = "googie_list_onhover";
-}
-GoogieSpell.item_onmouseout = function(e) {
-    var elm = AJS.getEventElm(e);
-    if(elm.className != "googie_list_revert" && elm.className != "googie_list_close")
-        elm.className = "googie_list_onout";
-    else
-        elm.parentNode.className = "googie_list_onout";
-}
+this.isDefined = function(o)
+{
+    return (o !== undefined && o !== null)
+};
 
-GoogieSpell.prototype.createCloseButton = function(c_fn) {
-    return this.createButton(this.lang_close, 'googie_list_close', AJS.$b(c_fn, this));
-}
+this.errorFixed = function()
+{
+    this.cnt_errors_fixed++;
+    if (this.all_errors_fixed_observer)
+        if (this.cnt_errors_fixed == this.cnt_errors) {
+            this.hideErrorWindow();
+            this.all_errors_fixed_observer();
+        }
+};
 
-GoogieSpell.prototype.createButton = function(name, css_class, c_fn) {
-    var btn_row = AJS.TR();
-    var btn = AJS.TD();
+this.errorFound = function()
+{
+    this.cnt_errors++;
+};
 
-    btn.onmouseover = GoogieSpell.item_onmouseover;
-    btn.onmouseout = GoogieSpell.item_onmouseout;
+this.createCloseButton = function(c_fn)
+{
+    return this.createButton(this.lang_close, 'googie_list_close', c_fn);
+};
 
-    var spn_btn;
-    if(css_class != "") {
-        spn_btn = AJS.SPAN({'class': css_class});
-        spn_btn.innerHTML = name;
+this.createButton = function(name, css_class, c_fn)
+{
+    var btn_row = document.createElement('tr'),
+        btn = document.createElement('td'),
+        spn_btn;
+
+    if (css_class) {
+        spn_btn = document.createElement('span');
+        $(spn_btn).addClass(css_class).html(name);
+    } else {
+        spn_btn = document.createTextNode(name);
     }
-    else {
-        spn_btn = AJS.TN(name);
-    }
+
+    $(btn).click(c_fn)
+        .mouseover(this.item_onmouseover)
+        .mouseout(this.item_onmouseout);
+
     btn.appendChild(spn_btn);
-    AJS.AEV(btn, "click", c_fn);
     btn_row.appendChild(btn);
 
     return btn_row;
-}
+};
 
-GoogieSpell.prototype.removeIndicator = function(elm) {
+this.removeIndicator = function(elm)
+{
+    //$(this.indicator).remove();
+    // roundcube mod.
+    if (window.rcmail)
+        rcmail.set_busy(false, null, this.rc_msg_id);
+};
+
+this.appendIndicator = function(elm)
+{
     // modified by roundcube
     if (window.rcmail)
-        rcmail.set_busy(false);
-    //try { AJS.removeElement(this.indicator); }
-    //catch(e) {}
+        this.rc_msg_id = rcmail.set_busy(true, 'checking');
+/*
+    this.indicator = document.createElement('img');
+    $(this.indicator).attr('src', this.img_dir + 'indicator.gif')
+        .css({'margin-right': '5px', 'text-decoration': 'none'}).width(16).height(16);
+
+    if (elm)
+        $(this.indicator).insertBefore(elm);
+    else
+        $('body').append(this.indicator);
+*/
 }
 
-GoogieSpell.prototype.appendIndicator = function(elm) {
-    // modified by roundcube
-    if (window.rcmail)
-        rcmail.set_busy(true, 'checking');
-  /*
-    var img = AJS.IMG({'src': this.img_dir + 'indicator.gif', 'style': 'margin-right: 5px;'});
-    AJS.setWidth(img, 16);
-    AJS.setHeight(img, 16);
-    this.indicator = img;
-    img.style.textDecoration = "none";
-    try {
-        AJS.insertBefore(img, elm);
-    }
-    catch(e) {}
-  */
-}
+this.createFocusLink = function(name)
+{
+    var link = document.createElement('a');
+    $(link).attr({'href': 'javascript:;', 'name': name});
+    return link;
+};
 
-GoogieSpell.prototype.createFocusLink = function(name) {
-    return AJS.A({'href': 'javascript:;', name: name});
-}
+this.item_onmouseover = function(e)
+{
+    if (this.className != 'googie_list_revert' && this.className != 'googie_list_close')
+        this.className = 'googie_list_onhover';
+    else
+        this.parentNode.className = 'googie_list_onhover';
+};
+
+this.item_onmouseout = function(e)
+{
+    if (this.className != 'googie_list_revert' && this.className != 'googie_list_close')
+        this.className = 'googie_list_onout';
+    else
+        this.parentNode.className = 'googie_list_onout';
+};
+
+
+};

--
Gitblit v1.9.1