Changeset 309d2f4 in github


Ignore:
Timestamp:
May 1, 2009 3:27:36 PM (4 years ago)
Author:
alecpl <alec@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
Children:
87b18e9
Parents:
1692499
Message:
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • program/js/app.js

    rffa6c10 r309d2f4  
    904904        else if (this.env.spellcheck && this.env.spellcheck.spellCheck && this.spellcheck_ready) { 
    905905          this.env.spellcheck.spellCheck(); 
     906          this.set_spellcheck_state('checking'); 
    906907        } 
    907908        break; 
     
    21132114    { 
    21142115    if (this.env.spellcheck && !this.spellcheck_ready) { 
    2115       exec_event(this.env.spellcheck.check_link, 'click'); 
     2116      $(this.env.spellcheck.spell_span).trigger('click'); 
    21162117      this.set_spellcheck_state('ready'); 
    21172118      } 
     
    21232124      // stop spellchecking process 
    21242125      if (!vis) 
    2125         this.stop_spellchecking(); 
    2126  
    2127       this.env.spellcheck.check_link.style.visibility = vis ? 'visible' : 'hidden'; 
    2128       this.env.spellcheck.switch_lan_pic.style.visibility = vis ? 'visible' : 'hidden'; 
     2126        this.stop_spellchecking(); 
     2127 
     2128      $(this.env.spellcheck.spell_container).css('visibility', vis ? 'visible' : 'hidden'); 
    21292129      } 
    21302130    }; 
     
    21322132  this.set_spellcheck_state = function(s) 
    21332133    { 
    2134     this.spellcheck_ready = (s=='check_spelling' || s=='spell_check' || s=='ready'); 
     2134    this.spellcheck_ready = (s == 'ready' || s == 'no_error_found'); 
    21352135    this.enable_command('spellcheck', this.spellcheck_ready); 
    21362136    }; 
  • program/js/common.js

    rcc97ea0 r309d2f4  
    635635    } 
    636636  } 
    637  
    638  
    639 // Fire event on specified element 
    640 function exec_event(element,event) 
    641  
    642   if (document.createEventObject) { 
    643     // dispatch for IE   
    644     var evt = document.createEventObject(); 
    645     return element.fireEvent('on'+event,evt) 
    646   } 
    647   else {   
    648     // dispatch for firefox + others   
    649     var evt = document.createEvent("HTMLEvents"); 
    650     evt.initEvent(event, true, true); // event type,bubbling,cancelable 
    651     return !element.dispatchEvent(evt); 
    652    } 
    653 } 
  • program/js/googiespell.js

    rffa6c10 r309d2f4  
    11/* 
    2 Last Modified: 29/04/07 18:44:48 
    3  
    4 AJS JavaScript library 
    5     A very small library with a lot of functionality 
    6 AUTHOR 
    7     4mir Salihefendic (http://amix.dk) - amix@amix.dk 
    8 LICENSE 
    9     Copyright (c) 2006 Amir Salihefendic. All rights reserved. 
    10     Copyright (c) 2005 Bob Ippolito. All rights reserved. 
    11     http://www.opensource.org/licenses/mit-license.php 
    12 VERSION 
    13     4.0 
    14 SITE 
    15     http://orangoo.com/AmiNation/AJS 
    16 **/ 
    17 if(!AJS) { 
    18 var AJS = { 
    19     BASE_URL: "", 
    20  
    21     drag_obj: null, 
    22     drag_elm: null, 
    23     _drop_zones: [], 
    24     _drag_zones: [], 
    25     _cur_pos: null, 
    26  
    27     ajaxErrorHandler: null, 
    28  
    29 //// 
    30 // General accessor functions 
    31 //// 
    32     getQueryArgument: function(var_name) { 
    33         var query = window.location.search.substring(1); 
    34         var vars = query.split("&"); 
    35         for (var i=0;i<vars.length;i++) { 
    36             var pair = vars[i].split("="); 
    37             if (pair[0] == var_name) { 
    38                 return pair[1]; 
    39             } 
    40         } 
    41         return null; 
    42     }, 
    43  
    44     isIe: function() { 
    45         return (navigator.userAgent.toLowerCase().indexOf("msie") != -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1); 
    46     }, 
    47     isNetscape7: function() { 
    48         return (navigator.userAgent.toLowerCase().indexOf("netscape") != -1 && navigator.userAgent.toLowerCase().indexOf("7.") != -1); 
    49     }, 
    50     isSafari: function() { 
    51         return (navigator.userAgent.toLowerCase().indexOf("khtml") != -1); 
    52     }, 
    53     isOpera: function() { 
    54         return (navigator.userAgent.toLowerCase().indexOf("opera") != -1); 
    55     }, 
    56     isMozilla: function() { 
    57         return (navigator.userAgent.toLowerCase().indexOf("gecko") != -1 && navigator.productSub >= 20030210); 
    58     }, 
    59     isMac: function() { 
    60         return (navigator.userAgent.toLowerCase().indexOf('macintosh') != -1); 
    61     }, 
    62  
    63  
    64 //// 
    65 // Array functions 
    66 //// 
    67     //Shortcut: AJS.$A 
    68     createArray: function(v) { 
    69         if(AJS.isArray(v) && !AJS.isString(v)) 
    70             return v; 
    71         else if(!v) 
    72             return []; 
    73         else 
    74             return [v]; 
    75     }, 
    76  
    77     forceArray: function(args) { 
    78         var r = []; 
    79         AJS.map(args, function(elm) { 
    80             r.push(elm); 
    81         }); 
    82         return r; 
    83     }, 
    84  
    85     join: function(delim, list) { 
    86         try { 
    87             return list.join(delim); 
    88         } 
    89         catch(e) { 
    90             var r = list[0] || ''; 
    91             AJS.map(list, function(elm) { 
    92                 r += delim + elm; 
    93             }, 1); 
    94             return r + ''; 
    95         } 
    96     }, 
    97  
    98     isIn: function(elm, list) { 
    99         var i = AJS.getIndex(elm, list); 
    100         if(i != -1) 
    101             return true; 
    102         else 
    103             return false; 
    104     }, 
    105  
    106     getIndex: function(elm, list/*optional*/, eval_fn) { 
    107         for(var i=0; i < list.length; i++) 
    108             if(eval_fn && eval_fn(list[i]) || elm == list[i]) 
    109                 return i; 
    110         return -1; 
    111     }, 
    112  
    113     getFirst: function(list) { 
    114         if(list.length > 0) 
    115             return list[0]; 
    116         else 
    117             return null; 
    118     }, 
    119  
    120     getLast: function(list) { 
    121         if(list.length > 0) 
    122             return list[list.length-1]; 
    123         else 
    124             return null; 
    125     }, 
    126  
    127     update: function(l1, l2) { 
    128         for(var i in l2) 
    129             l1[i] = l2[i]; 
    130         return l1; 
    131     }, 
    132  
    133     flattenList: function(list) { 
    134         var r = []; 
    135         var _flatten = function(r, l) { 
    136             AJS.map(l, function(o) { 
    137                 if(o == null) {} 
    138                 else if (AJS.isArray(o)) 
    139                     _flatten(r, o); 
    140                 else 
    141                     r.push(o); 
    142             }); 
    143         } 
    144         _flatten(r, list); 
    145         return r; 
    146     }, 
    147  
    148  
    149 //// 
    150 // Functional programming 
    151 //// 
    152     map: function(list, fn,/*optional*/ start_index, end_index) { 
    153         var i = 0, l = list.length; 
    154         if(start_index) 
    155              i = start_index; 
    156         if(end_index) 
    157              l = end_index; 
    158         for(i; i < l; i++) { 
    159             var val = fn.apply(null, [list[i], i]); 
    160             if(val != undefined) 
    161                 return val; 
    162         } 
    163     }, 
    164  
    165     rmap: function(list, fn) { 
    166         var i = list.length-1, l = 0; 
    167         for(i; i >= l; i--) { 
    168             var val = fn.apply(null, [list[i], i]); 
    169             if(val != undefined) 
    170                 return val; 
    171         } 
    172     }, 
    173  
    174     filter: function(list, fn, /*optional*/ start_index, end_index) { 
    175         var r = []; 
    176         AJS.map(list, function(elm) { 
    177             if(fn(elm)) 
    178                 r.push(elm); 
    179         }, start_index, end_index); 
    180         return r; 
    181     }, 
    182  
    183     partial: function(fn) { 
    184         var args = AJS.$FA(arguments); 
    185         args.shift(); 
    186         return function() { 
    187             args = args.concat(AJS.$FA(arguments)); 
    188             return fn.apply(window, args); 
    189         } 
    190     }, 
    191  
    192  
    193 //// 
    194 // DOM functions 
    195 //// 
    196     //Shortcut: AJS.$ 
    197     getElement: function(id) { 
    198         if(AJS.isString(id) || AJS.isNumber(id)) 
    199             return document.getElementById(id); 
    200         else 
    201             return id; 
    202     }, 
    203  
    204     //Shortcut: AJS.$$ 
    205     getElements: function(/*id1, id2, id3*/) { 
    206         var args = AJS.forceArray(arguments); 
    207         var elements = new Array(); 
    208             for (var i = 0; i < args.length; i++) { 
    209                 var element = AJS.getElement(args[i]); 
    210                 elements.push(element); 
    211             } 
    212             return elements; 
    213     }, 
    214  
    215     //Shortcut: AJS.$bytc 
    216     getElementsByTagAndClassName: function(tag_name, class_name, /*optional*/ parent) { 
    217         var class_elements = []; 
    218         if(!AJS.isDefined(parent)) 
    219             parent = document; 
    220         if(!AJS.isDefined(tag_name)) 
    221             tag_name = '*'; 
    222  
    223         var els = parent.getElementsByTagName(tag_name); 
    224         var els_len = els.length; 
    225         var pattern = new RegExp("(^|\\s)" + class_name + "(\\s|$)"); 
    226  
    227         for (i = 0, j = 0; i < els_len; i++) { 
    228             if ( pattern.test(els[i].className) || class_name == null ) { 
    229                 class_elements[j] = els[i]; 
    230                 j++; 
    231             } 
    232         } 
    233         return class_elements; 
    234     }, 
    235  
    236     _nodeWalk: function(elm, tag_name, class_name, fn_next_elm) { 
    237         var p = fn_next_elm(elm); 
    238  
    239         var checkFn; 
    240         if(tag_name && class_name) { 
    241             checkFn = function(p) { 
    242                 return AJS.nodeName(p) == tag_name && AJS.hasClass(p, class_name); 
    243             } 
    244         } 
    245         else if(tag_name) { 
    246             checkFn = function(p) { return AJS.nodeName(p) == tag_name; } 
    247         } 
    248         else { 
    249             checkFn = function(p) { return AJS.hasClass(p, class_name); } 
    250         } 
    251  
    252         while(p) { 
    253             if(checkFn(p)) 
    254                 return p; 
    255             p = fn_next_elm(p); 
    256         } 
    257         return null; 
    258     }, 
    259  
    260     getParentBytc: function(elm, tag_name, class_name) { 
    261         return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.parentNode; }); 
    262     }, 
    263  
    264     getPreviousSiblingBytc: function(elm, tag_name, class_name) { 
    265         return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.previousSibling; }); 
    266     }, 
    267  
    268     getNextSiblingBytc: function(elm, tag_name, class_name) { 
    269         return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.nextSibling; }); 
    270     }, 
    271  
    272     //Shortcut: AJS.$f 
    273     getFormElement: function(form, name) { 
    274         form = AJS.$(form); 
    275         var r = null; 
    276         AJS.map(form.elements, function(elm) { 
    277             if(elm.name && elm.name == name) 
    278                 r = elm; 
    279         }); 
    280         return r; 
    281     }, 
    282  
    283     formContents: function(form) { 
    284         var form = AJS.$(form); 
    285         var r = {}; 
    286         var fn = function(elms) { 
    287             AJS.map(elms, function(e) { 
    288                 if(e.name) 
    289                     r[e.name] = e.value || ''; 
    290             }); 
    291         } 
    292         fn(AJS.$bytc('input', null, form)); 
    293         fn(AJS.$bytc('textarea', null, form)); 
    294         return r; 
    295     }, 
    296  
    297     getBody: function() { 
    298         return AJS.$bytc('body')[0] 
    299     }, 
    300  
    301     nodeName: function(elm) { 
    302         return elm.nodeName.toLowerCase(); 
    303     }, 
    304  
    305     hasParent: function(elm, parent_to_consider, max_look_up) { 
    306         if(elm == parent_to_consider) 
    307             return true; 
    308         if(max_look_up == 0) 
    309             return false; 
    310         return AJS.hasParent(elm.parentNode, parent_to_consider, max_look_up-1); 
    311     }, 
    312  
    313     isElementHidden: function(elm) { 
    314         return ((elm.style.display == "none") || (elm.style.visibility == "hidden")); 
    315     }, 
    316  
    317     //Shortcut: AJS.DI 
    318     documentInsert: function(elm) { 
    319         if(typeof(elm) == 'string') 
    320             elm = AJS.HTML2DOM(elm); 
    321         document.write('<span id="dummy_holder"></span>'); 
    322         AJS.swapDOM(AJS.$('dummy_holder'), elm); 
    323     }, 
    324  
    325     cloner: function(element) { 
    326         return function() { 
    327             return element.cloneNode(true); 
    328         } 
    329     }, 
    330  
    331     appendToTop: function(elm/*, elms...*/) { 
    332         var args = AJS.forceArray(arguments).slice(1); 
    333         if(args.length >= 1) { 
    334             var first_child = elm.firstChild; 
    335             if(first_child) { 
    336                 while(true) { 
    337                     var t_elm = args.shift(); 
    338                     if(t_elm) 
    339                         AJS.insertBefore(t_elm, first_child); 
    340                     else 
    341                         break; 
    342                 } 
    343             } 
    344             else { 
    345                 AJS.ACN.apply(null, arguments); 
    346             } 
    347         } 
    348         return elm; 
    349     }, 
    350  
    351     //Shortcut: AJS.ACN 
    352     appendChildNodes: function(elm/*, elms...*/) { 
    353         if(arguments.length >= 2) { 
    354             AJS.map(arguments, function(n) { 
    355                 if(AJS.isString(n)) 
    356                     n = AJS.TN(n); 
    357                 if(AJS.isDefined(n)) 
    358                     elm.appendChild(n); 
    359             }, 1); 
    360         } 
    361         return elm; 
    362     }, 
    363  
    364     //Shortcut: AJS.RCN 
    365     replaceChildNodes: function(elm/*, elms...*/) { 
    366         var child; 
    367         while ((child = elm.firstChild)) 
    368             elm.removeChild(child); 
    369         if (arguments.length < 2) 
    370             return elm; 
    371         else 
    372             return AJS.appendChildNodes.apply(null, arguments); 
    373         return elm; 
    374     }, 
    375  
    376     insertAfter: function(elm, reference_elm) { 
    377         reference_elm.parentNode.insertBefore(elm, reference_elm.nextSibling); 
    378         return elm; 
    379     }, 
    380  
    381     insertBefore: function(elm, reference_elm) { 
    382         reference_elm.parentNode.insertBefore(elm, reference_elm); 
    383         return elm; 
    384     }, 
    385  
    386     showElement: function(/*elms...*/) { 
    387         var args = AJS.forceArray(arguments); 
    388         AJS.map(args, function(elm) { elm.style.display = ''}); 
    389     }, 
    390  
    391     hideElement: function(elm) { 
    392         var args = AJS.forceArray(arguments); 
    393         AJS.map(args, function(elm) { elm.style.display = 'none'}); 
    394     }, 
    395  
    396     swapDOM: function(dest, src) { 
    397         dest = AJS.getElement(dest); 
    398         var parent = dest.parentNode; 
    399         if (src) { 
    400             src = AJS.getElement(src); 
    401             parent.replaceChild(src, dest); 
    402         } else { 
    403             parent.removeChild(dest); 
    404         } 
    405         return src; 
    406     }, 
    407  
    408     removeElement: function(/*elm1, elm2...*/) { 
    409         var args = AJS.forceArray(arguments); 
    410         AJS.map(args, function(elm) { AJS.swapDOM(elm, null); }); 
    411     }, 
    412  
    413     createDOM: function(name, attrs) { 
    414         var i=0, attr; 
    415         elm = document.createElement(name); 
    416  
    417         if(AJS.isDict(attrs[i])) { 
    418             for(k in attrs[0]) { 
    419                 attr = attrs[0][k]; 
    420                 if(k == "style") 
    421                     elm.style.cssText = attr; 
    422                 else if(k == "class" || k == 'className') 
    423                     elm.className = attr; 
    424                 else { 
    425                     elm.setAttribute(k, attr); 
    426                 } 
    427             } 
    428             i++; 
    429         } 
    430  
    431         if(attrs[0] == null) 
    432             i = 1; 
    433  
    434         AJS.map(attrs, function(n) { 
    435             if(n) { 
    436                 if(AJS.isString(n) || AJS.isNumber(n)) 
    437                     n = AJS.TN(n); 
    438                 elm.appendChild(n); 
    439             } 
    440         }, i); 
    441         return elm; 
    442     }, 
    443  
    444     _createDomShortcuts: function() { 
    445         var elms = [ 
    446                 "ul", "li", "td", "tr", "th", 
    447                 "tbody", "table", "input", "span", "b", 
    448                 "a", "div", "img", "button", "h1", 
    449                 "h2", "h3", "br", "textarea", "form", 
    450                 "p", "select", "option", "optgroup", "iframe", "script", 
    451                 "center", "dl", "dt", "dd", "small", 
    452                 "pre" 
    453         ]; 
    454         var extends_ajs = function(elm) { 
    455             AJS[elm.toUpperCase()] = function() { 
    456                 return AJS.createDOM.apply(null, [elm, arguments]);  
    457             }; 
    458         } 
    459         AJS.map(elms, extends_ajs); 
    460         AJS.TN = function(text) { return document.createTextNode(text) }; 
    461     }, 
    462  
    463     getCssDim: function(dim) { 
    464         if(AJS.isString(dim)) 
    465             return dim; 
    466         else 
    467             return dim + "px"; 
    468     }, 
    469     getCssProperty: function(elm, prop) { 
    470         elm = AJS.$(elm); 
    471         var y; 
    472         if(elm.currentStyle) 
    473             y = elm.currentStyle[prop]; 
    474         else if (window.getComputedStyle) 
    475             y = document.defaultView.getComputedStyle(elm,null).getPropertyValue(prop); 
    476         return y; 
    477     }, 
    478  
    479     setStyle: function(/*elm1, elm2..., property, new_value*/) { 
    480         var args = AJS.forceArray(arguments); 
    481         var new_val = args.pop(); 
    482         var property = args.pop(); 
    483         AJS.map(args, function(elm) {  
    484             elm.style[property] = AJS.getCssDim(new_val); 
    485         }); 
    486     }, 
    487  
    488     setWidth: function(/*elm1, elm2..., width*/) { 
    489         var args = AJS.forceArray(arguments); 
    490         args.splice(args.length-1, 0, 'width'); 
    491         AJS.setStyle.apply(null, args); 
    492     }, 
    493     setHeight: function(/*elm1, elm2..., height*/) { 
    494         var args = AJS.forceArray(arguments); 
    495         args.splice(args.length-1, 0, 'height'); 
    496         AJS.setStyle.apply(null, args); 
    497     }, 
    498     setLeft: function(/*elm1, elm2..., left*/) { 
    499         var args = AJS.forceArray(arguments); 
    500         args.splice(args.length-1, 0, 'left'); 
    501         AJS.setStyle.apply(null, args); 
    502     }, 
    503     setTop: function(/*elm1, elm2..., top*/) { 
    504         var args = AJS.forceArray(arguments); 
    505         args.splice(args.length-1, 0, 'top'); 
    506         AJS.setStyle.apply(null, args); 
    507     }, 
    508     setClass: function(/*elm1, elm2..., className*/) { 
    509         var args = AJS.forceArray(arguments); 
    510         var c = args.pop(); 
    511         AJS.map(args, function(elm) { elm.className = c}); 
    512     }, 
    513     addClass: function(/*elm1, elm2..., className*/) { 
    514         var args = AJS.forceArray(arguments); 
    515         var cls = args.pop(); 
    516         var add_class = function(o) { 
    517             if(!new RegExp("(^|\\s)" + cls + "(\\s|$)").test(o.className)) 
    518                 o.className += (o.className ? " " : "") + cls; 
    519         }; 
    520         AJS.map(args, function(elm) { add_class(elm); }); 
    521     }, 
    522     hasClass: function(elm, cls) { 
    523         if(!elm.className) 
    524             return false; 
    525         return elm.className == cls ||  
    526                elm.className.search(new RegExp(" " + cls + "|^" + cls)) != -1 
    527     }, 
    528     removeClass: function(/*elm1, elm2..., className*/) { 
    529         var args = AJS.forceArray(arguments); 
    530         var cls = args.pop(); 
    531         var rm_class = function(o) { 
    532             o.className = o.className.replace(new RegExp("\\s?" + cls, 'g'), ""); 
    533         }; 
    534         AJS.map(args, function(elm) { rm_class(elm); }); 
    535     }, 
    536  
    537     setHTML: function(elm, html) { 
    538         elm.innerHTML = html; 
    539         return elm; 
    540     }, 
    541  
    542     RND: function(tmpl, ns, scope) { 
    543         scope = scope || window; 
    544         var fn = function(w, g) { 
    545             g = g.split("|"); 
    546             var cnt = ns[g[0]]; 
    547             for(var i=1; i < g.length; i++) 
    548                 cnt = scope[g[i]](cnt); 
    549             if(cnt == '') 
    550                 return ''; 
    551             if(cnt == 0 || cnt == -1) 
    552                 cnt += ''; 
    553             return cnt || w; 
    554         }; 
    555         return tmpl.replace(/%\(([A-Za-z0-9_|.]*)\)/g, fn); 
    556     }, 
    557  
    558     HTML2DOM: function(html,/*optional*/ first_child) { 
    559         var d = AJS.DIV(); 
    560         d.innerHTML = html; 
    561         if(first_child) 
    562             return d.childNodes[0]; 
    563         else 
    564             return d; 
    565     }, 
    566  
    567     preloadImages: function(/*img_src1, ..., img_srcN*/) { 
    568         AJS.AEV(window, 'load', AJS.$p(function(args) { 
    569             AJS.map(args, function(src) { 
    570                 var pic = new Image(); 
    571                 pic.src = src; 
    572             }); 
    573         }, arguments)); 
    574     }, 
    575  
    576  
    577 //// 
    578 // Effects 
    579 //// 
    580     setOpacity: function(elm, p) { 
    581         elm.style.opacity = p; 
    582         elm.style.filter = "alpha(opacity="+ p*100 +")"; 
    583     }, 
    584  
    585     resetOpacity: function(elm) { 
    586         elm.style.opacity = 1; 
    587         elm.style.filter = ""; 
    588     }, 
    589  
    590 //// 
    591 // Ajax functions 
    592 //// 
    593     getXMLHttpRequest: function() { 
    594         var try_these = [ 
    595             function () { return new XMLHttpRequest(); }, 
    596             function () { return new ActiveXObject('Msxml2.XMLHTTP'); }, 
    597             function () { return new ActiveXObject('Microsoft.XMLHTTP'); }, 
    598             function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); }, 
    599             function () { throw "Browser does not support XMLHttpRequest"; } 
    600         ]; 
    601         for (var i = 0; i < try_these.length; i++) { 
    602             var func = try_these[i]; 
    603             try { 
    604                 return func(); 
    605             } catch (e) { 
    606             } 
    607         } 
    608     }, 
    609  
    610     getRequest: function(url, data, type) { 
    611         if(!type) 
    612             type = "POST"; 
    613         var req = AJS.getXMLHttpRequest(); 
    614  
    615         if(url.indexOf("http://") == -1) { 
    616             if(AJS.BASE_URL != '') { 
    617                 if(AJS.BASE_URL.lastIndexOf('/') != AJS.BASE_URL.length-1) 
    618                     AJS.BASE_URL += '/'; 
    619                 url = AJS.BASE_URL + url; 
    620             } 
    621         } 
    622  
    623         req.open(type, url, true); 
    624         if(type == "POST") 
    625             req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
    626         return AJS._sendXMLHttpRequest(req); 
    627     }, 
    628  
    629     _sendXMLHttpRequest: function(req, data) { 
    630         var d = new AJSDeferred(req); 
    631  
    632         var onreadystatechange = function () { 
    633             if (req.readyState == 4) { 
    634                 var status = ''; 
    635                 try { 
    636                     status = req.status; 
    637                 } 
    638                 catch(e) {}; 
    639                 if(status == 200 || status == 304 || req.responseText == null) { 
    640                     d.callback(); 
    641                 } 
    642                 else { 
    643                     if(d.errbacks.length == 0) { 
    644                         if(AJS.ajaxErrorHandler) 
    645                             AJS.ajaxErrorHandler(req.responseText, req); 
    646                     } 
    647                     else  
    648                         d.errback(); 
    649                 } 
    650             } 
    651         } 
    652         req.onreadystatechange = onreadystatechange; 
    653         return d; 
    654     }, 
    655  
    656     _reprString: function(o) { 
    657         return ('"' + o.replace(/(["\\])/g, '\\$1') + '"' 
    658         ).replace(/[\f]/g, "\\f" 
    659         ).replace(/[\b]/g, "\\b" 
    660         ).replace(/[\n]/g, "\\n" 
    661         ).replace(/[\t]/g, "\\t" 
    662         ).replace(/[\r]/g, "\\r"); 
    663     }, 
    664  
    665     _reprDate: function(db) { 
    666         var year = db.getFullYear(); 
    667         var dd = db.getDate(); 
    668         var mm = db.getMonth()+1; 
    669  
    670         var hh = db.getHours(); 
    671         var mins = db.getMinutes(); 
    672  
    673         function leadingZero(nr) { 
    674             if (nr < 10) nr = "0" + nr; 
    675             return nr; 
    676         } 
    677         if(hh == 24) hh = '00'; 
    678  
    679         var time = leadingZero(hh) + ':' + leadingZero(mins); 
    680         return '"' + year + '-' + mm + '-' + dd + 'T' + time + '"'; 
    681     }, 
    682  
    683     serializeJSON: function(o) { 
    684         var objtype = typeof(o); 
    685         if (objtype == "undefined") { 
    686             return "undefined"; 
    687         } else if (objtype == "number" || objtype == "boolean") { 
    688             return o + ""; 
    689         } else if (o === null) { 
    690             return "null"; 
    691         } 
    692         if (objtype == "string") { 
    693             return AJS._reprString(o); 
    694         } 
    695         if(objtype == 'object' && o.getFullYear) { 
    696             return AJS._reprDate(o); 
    697         } 
    698         var me = arguments.callee; 
    699         if (objtype != "function" && typeof(o.length) == "number") { 
    700             var res = []; 
    701             for (var i = 0; i < o.length; i++) { 
    702                 var val = me(o[i]); 
    703                 if (typeof(val) != "string") { 
    704                     val = "undefined"; 
    705                 } 
    706                 res.push(val); 
    707             } 
    708             return "[" + res.join(",") + "]"; 
    709         } 
    710         // it's a function with no adapter, bad 
    711         if (objtype == "function") 
    712             return null; 
    713         res = []; 
    714         for (var k in o) { 
    715             var useKey; 
    716             if (typeof(k) == "number") { 
    717                 useKey = '"' + k + '"'; 
    718             } else if (typeof(k) == "string") { 
    719                 useKey = AJS._reprString(k); 
    720             } else { 
    721                 // skip non-string or number keys 
    722                 continue; 
    723             } 
    724             val = me(o[k]); 
    725             if (typeof(val) != "string") { 
    726                 // skip non-serializable values 
    727                 continue; 
    728             } 
    729             res.push(useKey + ":" + val); 
    730         } 
    731         return "{" + res.join(",") + "}"; 
    732     }, 
    733  
    734     loadJSONDoc: function(url) { 
    735         var d = AJS.getRequest(url); 
    736         var eval_req = function(data, req) { 
    737             var text = req.responseText; 
    738             if(text == "Error") 
    739                 d.errback(req); 
    740             else 
    741                 return AJS.evalTxt(text); 
    742         }; 
    743         d.addCallback(eval_req); 
    744         return d; 
    745     }, 
    746  
    747     evalTxt: function(txt) { 
    748         try { 
    749             return eval('('+ txt + ')'); 
    750         } 
    751         catch(e) { 
    752             return eval(txt); 
    753         } 
    754     }, 
    755  
    756     evalScriptTags: function(html) { 
    757         var script_data = html.match(/<script.*?>((\n|\r|.)*?)<\/script>/g); 
    758         if(script_data != null) { 
    759             for(var i=0; i < script_data.length; i++) { 
    760                 var script_only = script_data[i].replace(/<script.*?>/g, ""); 
    761                 script_only = script_only.replace(/<\/script>/g, ""); 
    762                 eval(script_only); 
    763             } 
    764         } 
    765     }, 
    766  
    767     queryArguments: function(data) { 
    768         var post_data = []; 
    769         for(k in data) 
    770             post_data.push(k + "=" + AJS.urlencode(data[k])); 
    771         return post_data.join("&"); 
    772     }, 
    773  
    774  
    775 //// 
    776 // Position and size 
    777 //// 
    778     getMousePos: function(e) { 
    779         var posx = 0; 
    780         var posy = 0; 
    781         if (!e) var e = window.event; 
    782         if (e.pageX || e.pageY) { 
    783             posx = e.pageX; 
    784             posy = e.pageY; 
    785         } 
    786         else if (e.clientX || e.clientY) { 
    787             posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
    788             posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
    789         } 
    790         return {x: posx, y: posy}; 
    791     }, 
    792  
    793     getScrollTop: function() { 
    794         //From: http://www.quirksmode.org/js/doctypes.html 
    795         var t; 
    796         if (document.documentElement && document.documentElement.scrollTop) 
    797                 t = document.documentElement.scrollTop; 
    798         else if (document.body) 
    799                 t = document.body.scrollTop; 
    800         return t; 
    801     }, 
    802  
    803     absolutePosition: function(elm) { 
    804         var posObj = {'x': elm.offsetLeft, 'y': elm.offsetTop}; 
    805  
    806         if(elm.offsetParent) { 
    807             var next = elm.offsetParent; 
    808             while(next) { 
    809                 posObj.x += next.offsetLeft; 
    810                 posObj.y += next.offsetTop; 
    811                 next = next.offsetParent; 
    812             } 
    813         } 
    814         // safari bug 
    815         if (AJS.isSafari() && elm.style.position == 'absolute' ) { 
    816             posObj.x -= document.body.offsetLeft; 
    817             posObj.y -= document.body.offsetTop; 
    818         } 
    819         return posObj; 
    820     }, 
    821  
    822     getWindowSize: function(doc) { 
    823         doc = doc || document; 
    824         var win_w, win_h; 
    825         if (self.innerHeight) { 
    826             win_w = self.innerWidth; 
    827             win_h = self.innerHeight; 
    828         } else if (doc.documentElement && doc.documentElement.clientHeight) { 
    829             win_w = doc.documentElement.clientWidth; 
    830             win_h = doc.documentElement.clientHeight; 
    831         } else if (doc.body) { 
    832             win_w = doc.body.clientWidth; 
    833             win_h = doc.body.clientHeight; 
    834         } 
    835         return {'w': win_w, 'h': win_h}; 
    836     }, 
    837  
    838     isOverlapping: function(elm1, elm2) { 
    839         var pos_elm1 = AJS.absolutePosition(elm1); 
    840         var pos_elm2 = AJS.absolutePosition(elm2); 
    841  
    842         var top1 = pos_elm1.y; 
    843         var left1 = pos_elm1.x; 
    844         var right1 = left1 + elm1.offsetWidth; 
    845         var bottom1 = top1 + elm1.offsetHeight; 
    846         var top2 = pos_elm2.y; 
    847         var left2 = pos_elm2.x; 
    848         var right2 = left2 + elm2.offsetWidth; 
    849         var bottom2 = top2 + elm2.offsetHeight; 
    850         var getSign = function(v) { 
    851             if(v > 0) return "+"; 
    852             else if(v < 0) return "-"; 
    853             else return 0; 
    854         } 
    855  
    856         if ((getSign(top1 - bottom2) != getSign(bottom1 - top2)) && 
    857                 (getSign(left1 - right2) != getSign(right1 - left2))) 
    858             return true; 
    859         return false; 
    860     }, 
    861  
    862  
    863 //// 
    864 // Events 
    865 //// 
    866     getEventElm: function(e) { 
    867         if(e && !e.type && !e.keyCode) 
    868             return e 
    869         var targ; 
    870         if (!e) var e = window.event; 
    871         if (e.target) targ = e.target; 
    872         else if (e.srcElement) targ = e.srcElement; 
    873         if (targ.nodeType == 3) // defeat Safari bug 
    874             targ = targ.parentNode; 
    875         return targ; 
    876     }, 
    877  
    878     _getRealScope: function(fn, /*optional*/ extra_args) { 
    879         extra_args = AJS.$A(extra_args); 
    880         var scope = fn._cscope || window; 
    881  
    882         return function() { 
    883             var args = AJS.$FA(arguments).concat(extra_args); 
    884             return fn.apply(scope, args); 
    885         }; 
    886     }, 
    887  
    888     _unloadListeners: function() { 
    889         if(AJS.listeners) 
    890             AJS.map(AJS.listeners, function(elm, type, fn) { AJS.REV(elm, type, fn) }); 
    891         AJS.listeners = []; 
    892     }, 
    893  
    894     setEventKey: function(e) { 
    895         e.key = e.keyCode ? e.keyCode : e.charCode; 
    896  
    897         if(window.event) { 
    898             e.ctrl = window.event.ctrlKey; 
    899             e.shift = window.event.shiftKey; 
    900         } 
    901         else { 
    902             e.ctrl = e.ctrlKey; 
    903             e.shift = e.shiftKey; 
    904         } 
    905         switch(e.key) { 
    906             case 63232: 
    907                 e.key = 38; 
    908                 break; 
    909             case 63233: 
    910                 e.key = 40; 
    911                 break; 
    912             case 63235: 
    913                 e.key = 39; 
    914                 break; 
    915             case 63234: 
    916                 e.key = 37; 
    917                 break; 
    918         } 
    919     }, 
    920  
    921     //Shortcut: AJS.AEV 
    922     addEventListener: function(elm, type, fn, /*optional*/listen_once, cancle_bubble) { 
    923         if(!cancle_bubble) 
    924             cancle_bubble = false; 
    925  
    926         var elms = AJS.$A(elm); 
    927         AJS.map(elms, function(elmz) { 
    928             if(listen_once) 
    929                 fn = AJS._listenOnce(elmz, type, fn); 
    930              
    931             //Hack since it does not work in all browsers 
    932             if(AJS.isIn(type, ['submit', 'load', 'scroll', 'resize'])) { 
    933                 var old = elm['on' + type]; 
    934                 elm['on' + type] = function() { 
    935                     if(old) { 
    936                         fn(arguments); 
    937                         return old(arguments); 
    938                     } 
    939                     else 
    940                         return fn(arguments); 
    941                 }; 
    942                 return; 
    943             } 
    944  
    945             //Fix keyCode 
    946             if(AJS.isIn(type, ['keypress', 'keydown', 'keyup', 'click'])) { 
    947                 var old_fn = fn; 
    948                 fn = function(e) { 
    949                     AJS.setEventKey(e); 
    950                     return old_fn.apply(null, arguments); 
    951                 } 
    952             } 
    953  
    954             if (elmz.attachEvent) { 
    955                 //FIXME: We ignore cancle_bubble for IE... could be a problem? 
    956                 elmz.attachEvent("on" + type, fn); 
    957             } 
    958             else if(elmz.addEventListener) 
    959                 elmz.addEventListener(type, fn, cancle_bubble); 
    960  
    961             AJS.listeners = AJS.$A(AJS.listeners); 
    962             AJS.listeners.push([elmz, type, fn]); 
    963         }); 
    964     }, 
    965  
    966     //Shortcut: AJS.REV 
    967     removeEventListener: function(elm, type, fn, /*optional*/cancle_bubble) { 
    968         if(!cancle_bubble) 
    969             cancle_bubble = false; 
    970         if(elm.removeEventListener) { 
    971             elm.removeEventListener(type, fn, cancle_bubble); 
    972             if(AJS.isOpera()) 
    973                 elm.removeEventListener(type, fn, !cancle_bubble); 
    974         } 
    975         else if(elm.detachEvent) 
    976             elm.detachEvent("on" + type, fn); 
    977     }, 
    978  
    979     //Shortcut: AJS.$b 
    980     bind: function(fn, scope, /*optional*/ extra_args) { 
    981         fn._cscope = scope; 
    982         return AJS._getRealScope(fn, extra_args); 
    983     }, 
    984  
    985     bindMethods: function(self) { 
    986         for (var k in self) { 
    987             var func = self[k]; 
    988             if (typeof(func) == 'function') { 
    989                 self[k] = AJS.$b(func, self); 
    990             } 
    991         } 
    992     }, 
    993  
    994     _listenOnce: function(elm, type, fn) { 
    995         var r_fn = function() { 
    996             AJS.removeEventListener(elm, type, r_fn); 
    997             fn(arguments); 
    998         } 
    999         return r_fn; 
    1000     }, 
    1001  
    1002     callLater: function(fn, interval) { 
    1003         var fn_no_send = function() { 
    1004             fn(); 
    1005         }; 
    1006         window.setTimeout(fn_no_send, interval); 
    1007     }, 
    1008  
    1009     preventDefault: function(e) { 
    1010         if(AJS.isIe())  
    1011             window.event.returnValue = false; 
    1012         else  
    1013             e.preventDefault(); 
    1014     }, 
    1015  
    1016  
    1017 //// 
    1018 // Drag and drop 
    1019 //// 
    1020     dragAble: function(elm, /*optional*/ handler, args) { 
    1021         if(!args) 
    1022             args = {}; 
    1023         if(!AJS.isDefined(args['move_x'])) 
    1024             args['move_x'] = true; 
    1025         if(!AJS.isDefined(args['move_y'])) 
    1026             args['move_y'] = true; 
    1027         if(!AJS.isDefined(args['moveable'])) 
    1028             args['moveable'] = false; 
    1029         if(!AJS.isDefined(args['hide_on_move'])) 
    1030             args['hide_on_move'] = true; 
    1031         if(!AJS.isDefined(args['on_mouse_up'])) 
    1032             args['on_mouse_up'] = null; 
    1033         if(!AJS.isDefined(args['cursor'])) 
    1034             args['cursor'] = 'move'; 
    1035         if(!AJS.isDefined(args['max_move'])) 
    1036             args['max_move'] = {'top': null, 'left': null}; 
    1037  
    1038         elm = AJS.$(elm); 
    1039  
    1040         if(!handler) 
    1041             handler = elm; 
    1042  
    1043         handler = AJS.$(handler); 
    1044         var old_cursor = handler.style.cursor; 
    1045         handler.style.cursor = args['cursor']; 
    1046         elm.style.position = 'relative'; 
    1047  
    1048         AJS.addClass(handler, '_ajs_handler'); 
    1049         handler._args = args; 
    1050         handler._elm = elm; 
    1051         AJS.AEV(handler, 'mousedown', AJS._dragStart); 
    1052     }, 
    1053  
    1054     _dragStart: function(e) { 
    1055         var handler = AJS.getEventElm(e); 
    1056         if(!AJS.hasClass(handler, '_ajs_handler')) { 
    1057             handler = AJS.getParentBytc(handler, null, '_ajs_handler'); 
    1058         } 
    1059         if(handler) 
    1060             AJS._dragInit(e, handler._elm, handler._args); 
    1061     }, 
    1062  
    1063     dropZone: function(elm, args) { 
    1064         elm = AJS.$(elm); 
    1065         var item = {elm: elm}; 
    1066         AJS.update(item, args); 
    1067         AJS._drop_zones.push(item); 
    1068     }, 
    1069  
    1070     removeDragAble: function(elm) { 
    1071         AJS.REV(elm, 'mousedown', AJS._dragStart); 
    1072         elm.style.cursor = ''; 
    1073     }, 
    1074  
    1075     removeDropZone: function(elm) { 
    1076         var i = AJS.getIndex(elm, AJS._drop_zones, function(item) { 
    1077             if(item.elm == elm) return true; 
    1078         }); 
    1079         if(i != -1) { 
    1080             AJS._drop_zones.splice(i, 1); 
    1081         } 
    1082     }, 
    1083  
    1084     _dragInit: function(e, click_elm, args) { 
    1085         AJS.drag_obj = new Object(); 
    1086         AJS.drag_obj.args = args; 
    1087  
    1088         AJS.drag_obj.click_elm = click_elm; 
    1089         AJS.drag_obj.mouse_pos = AJS.getMousePos(e); 
    1090         AJS.drag_obj.click_elm_pos = AJS.absolutePosition(click_elm); 
    1091  
    1092         AJS.AEV(document, 'mousemove', AJS._dragMove, false, true); 
    1093         AJS.AEV(document, 'mouseup', AJS._dragStop, false, true); 
    1094  
    1095         if (AJS.isIe()) 
    1096             window.event.cancelBubble = true; 
    1097         AJS.preventDefault(e); 
    1098     }, 
    1099  
    1100     _initDragElm: function(elm) { 
    1101         if(AJS.drag_elm && AJS.drag_elm.style.display == 'none') 
    1102             AJS.removeElement(AJS.drag_elm); 
    1103  
    1104         if(!AJS.drag_elm) { 
    1105             AJS.drag_elm = AJS.DIV(); 
    1106             var d = AJS.drag_elm; 
    1107             AJS.insertBefore(d, AJS.getBody().firstChild); 
    1108             AJS.setHTML(d, elm.innerHTML); 
    1109  
    1110             d.className = elm.className; 
    1111             d.style.cssText = elm.style.cssText; 
    1112  
    1113             d.style.position = 'absolute'; 
    1114             d.style.zIndex = 10000; 
    1115  
    1116             var t = AJS.absolutePosition(elm); 
    1117             AJS.setTop(d, t.y); 
    1118             AJS.setLeft(d, t.x); 
    1119  
    1120             if(AJS.drag_obj.args.on_init) { 
    1121                 AJS.drag_obj.args.on_init(elm); 
    1122             } 
    1123         } 
    1124     }, 
    1125  
    1126     _dragMove: function(e) { 
    1127         var drag_obj = AJS.drag_obj; 
    1128         var click_elm = drag_obj.click_elm; 
    1129  
    1130         AJS._initDragElm(click_elm); 
    1131         var drag_elm = AJS.drag_elm; 
    1132  
    1133         if(drag_obj.args['hide_on_move']) 
    1134             click_elm.style.visibility = 'hidden'; 
    1135  
    1136         var cur_pos = AJS.getMousePos(e); 
    1137  
    1138         var mouse_pos = drag_obj.mouse_pos; 
    1139  
    1140         var click_elm_pos = drag_obj.click_elm_pos; 
    1141  
    1142         var p_x, p_y; 
    1143         p_x = cur_pos.x - (mouse_pos.x - click_elm_pos.x); 
    1144         p_y = cur_pos.y - (mouse_pos.y - click_elm_pos.y); 
    1145  
    1146         AJS.map(AJS._drop_zones, function(d_z) { 
    1147             if(AJS.isOverlapping(d_z['elm'], drag_elm)) { 
    1148                 if(d_z['elm'] != drag_elm) { 
    1149                     var on_hover = d_z['on_hover']; 
    1150                     if(on_hover) 
    1151                         on_hover(d_z['elm'], click_elm, drag_elm); 
    1152                 } 
    1153             } 
    1154         }); 
    1155  
    1156         if(drag_obj.args['on_drag']) 
    1157             drag_obj.args['on_drag'](click_elm, e); 
    1158  
    1159         var max_move_top = drag_obj.args['max_move']['top']; 
    1160         var max_move_left = drag_obj.args['max_move']['left']; 
    1161         if(drag_obj.args['move_x']) { 
    1162             if(max_move_left == null || max_move_left <= p) 
    1163                 AJS.setLeft(elm, p_x); 
    1164         } 
    1165  
    1166         if(drag_obj.args['move_y']) { 
    1167             if(max_move_top == null || max_move_top <= p_y) 
    1168                 AJS.setTop(elm, p_y); 
    1169         } 
    1170         if(AJS.isIe()) { 
    1171             window.event.cancelBubble = true; 
    1172             window.event.returnValue = false; 
    1173         } 
    1174         else 
    1175             e.preventDefault(); 
    1176  
    1177         //Moving scroll to the top, should move the scroll up 
    1178         var sc_top = AJS.getScrollTop(); 
    1179         var sc_bottom = sc_top + AJS.getWindowSize().h; 
    1180         var d_e_top = AJS.absolutePosition(drag_elm).y; 
    1181         var d_e_bottom = drag_elm.offsetTop + drag_elm.offsetHeight; 
    1182  
    1183         if(d_e_top <= sc_top + 20) { 
    1184             window.scrollBy(0, -15); 
    1185         } 
    1186         else if(d_e_bottom >= sc_bottom - 20) { 
    1187             window.scrollBy(0, 15); 
    1188         } 
    1189     }, 
    1190  
    1191     _dragStop: function(e) { 
    1192         var drag_obj = AJS.drag_obj; 
    1193         var drag_elm = AJS.drag_elm; 
    1194         var click_elm = drag_obj.click_elm; 
    1195  
    1196         AJS.REV(document, "mousemove", AJS._dragMove, true); 
    1197         AJS.REV(document, "mouseup", AJS._dragStop, true); 
    1198  
    1199         var dropped = false; 
    1200         AJS.map(AJS._drop_zones, function(d_z) { 
    1201             if(AJS.isOverlapping(d_z['elm'], click_elm)) { 
    1202                 if(d_z['elm'] != click_elm) { 
    1203                     var on_drop = d_z['on_drop']; 
    1204                     if(on_drop) { 
    1205                         dropped = true; 
    1206                         on_drop(d_z['elm'], click_elm); 
    1207                     } 
    1208                 } 
    1209             } 
    1210         }); 
    1211  
    1212         if(drag_obj.args['moveable']) { 
    1213             var t = parseInt(click_elm.style.top) || 0; 
    1214             var l = parseInt(click_elm.style.left) || 0; 
    1215             var drag_elm_xy = AJS.absolutePosition(drag_elm); 
    1216             var click_elm_xy = AJS.absolutePosition(click_elm); 
    1217             AJS.setTop(click_elm, t + drag_elm_xy.y - click_elm_xy.y); 
    1218             AJS.setLeft(click_elm, l + drag_elm_xy.x - click_elm_xy.x); 
    1219         } 
    1220  
    1221         if(!dropped && drag_obj.args['on_mouse_up']) 
    1222             drag_obj.args['on_mouse_up'](click_elm, e); 
    1223  
    1224         if(drag_obj.args['hide_on_move']) 
    1225             drag_obj.click_elm.style.visibility = 'visible'; 
    1226  
    1227         if(drag_obj.args.on_end) { 
    1228             drag_obj.args.on_end(click_elm); 
    1229         } 
    1230  
    1231         AJS._dragObj = null; 
    1232         if(drag_elm) 
    1233             AJS.hideElement(drag_elm); 
    1234         AJS.drag_elm = null; 
    1235     }, 
    1236  
    1237  
    1238 //// 
    1239 // Misc. 
    1240 //// 
    1241     keys: function(obj) { 
    1242         var rval = []; 
    1243         for (var prop in obj) { 
    1244             rval.push(prop); 
    1245         } 
    1246         return rval; 
    1247     }, 
    1248  
    1249     values: function(obj) { 
    1250         var rval = []; 
    1251         for (var prop in obj) { 
    1252             rval.push(obj[prop]); 
    1253         } 
    1254         return rval; 
    1255     }, 
    1256  
    1257     urlencode: function(str) { 
    1258         return encodeURIComponent(str.toString()); 
    1259     }, 
    1260  
    1261     isDefined: function(o) { 
    1262         return (o != "undefined" && o != null) 
    1263     }, 
    1264  
    1265     isArray: function(obj) { 
    1266         return obj instanceof Array; 
    1267     }, 
    1268  
    1269     isString: function(obj) { 
    1270         return (typeof obj == 'string'); 
    1271     }, 
    1272  
    1273     isNumber: function(obj) { 
    1274         return (typeof obj == 'number'); 
    1275     }, 
    1276  
    1277     isObject: function(obj) { 
    1278         return (typeof obj == 'object'); 
    1279     }, 
    1280  
    1281     isFunction: function(obj) { 
    1282         return (typeof obj == 'function'); 
    1283     }, 
    1284  
    1285     isDict: function(o) { 
    1286         var str_repr = String(o); 
    1287         return str_repr.indexOf(" Object") != -1; 
    1288     }, 
    1289  
    1290     exportToGlobalScope: function() { 
    1291         for(e in AJS) 
    1292             window[e] = AJS[e]; 
    1293     }, 
    1294  
    1295     log: function(o) { 
    1296         if(window.console) 
    1297             console.log(o); 
    1298         else { 
    1299             var div = AJS.$('ajs_logger'); 
    1300             if(!div) { 
    1301                 div = AJS.DIV({id: 'ajs_logger', 'style': 'color: green; position: absolute; left: 0'}); 
    1302                 div.style.top = AJS.getScrollTop() + 'px'; 
    1303                 AJS.ACN(AJS.getBody(), div); 
    1304             } 
    1305             AJS.setHTML(div, ''+o); 
    1306         } 
    1307     } 
    1308  
    1309 } 
    1310  
    1311 AJS.Class = function(members) { 
    1312     var fn = function() { 
    1313         if(arguments[0] != 'no_init') { 
    1314             return this.init.apply(this, arguments); 
    1315         } 
    1316     } 
    1317     fn.prototype = members; 
    1318     AJS.update(fn, AJS.Class.prototype); 
    1319     return fn; 
    1320 } 
    1321 AJS.Class.prototype = { 
    1322     extend: function(members) { 
    1323         var parent = new this('no_init'); 
    1324         for(k in members) { 
    1325             var prev = parent[k]; 
    1326             var cur = members[k]; 
    1327             if (prev && prev != cur && typeof cur == 'function') { 
    1328                 cur = this._parentize(cur, prev); 
    1329             } 
    1330             parent[k] = cur; 
    1331         } 
    1332         return new AJS.Class(parent); 
    1333     }, 
    1334  
    1335     implement: function(members) { 
    1336         AJS.update(this.prototype, members); 
    1337     }, 
    1338  
    1339     _parentize: function(cur, prev) { 
    1340         return function(){ 
    1341             this.parent = prev; 
    1342             return cur.apply(this, arguments); 
    1343         } 
    1344     } 
    1345 }; 
    1346  
    1347 //Shortcuts 
    1348 AJS.$ = AJS.getElement; 
    1349 AJS.$$ = AJS.getElements; 
    1350 AJS.$f = AJS.getFormElement; 
    1351 AJS.$b = AJS.bind; 
    1352 AJS.$p = AJS.partial; 
    1353 AJS.$FA = AJS.forceArray; 
    1354 AJS.$A = AJS.createArray; 
    1355 AJS.DI = AJS.documentInsert; 
    1356 AJS.ACN = AJS.appendChildNodes; 
    1357 AJS.RCN = AJS.replaceChildNodes; 
    1358 AJS.AEV = AJS.addEventListener; 
    1359 AJS.REV = AJS.removeEventListener; 
    1360 AJS.$bytc = AJS.getElementsByTagAndClassName; 
    1361  
    1362 AJSDeferred = function(req) { 
    1363     this.callbacks = []; 
    1364     this.errbacks = []; 
    1365     this.req = req; 
    1366 } 
    1367 AJSDeferred.prototype = { 
    1368     excCallbackSeq: function(req, list) { 
    1369         var data = req.responseText; 
    1370         while (list.length > 0) { 
    1371             var fn = list.pop(); 
    1372             var new_data = fn(data, req); 
    1373             if(new_data) 
    1374                 data = new_data; 
    1375         } 
    1376     }, 
    1377  
    1378     callback: function () { 
    1379         this.excCallbackSeq(this.req, this.callbacks); 
    1380     }, 
    1381  
    1382     errback: function() { 
    1383         if(this.errbacks.length == 0) 
    1384             alert("Error encountered:\n" + this.req.responseText); 
    1385  
    1386         this.excCallbackSeq(this.req, this.errbacks); 
    1387     }, 
    1388  
    1389     addErrback: function(fn) { 
    1390         this.errbacks.unshift(fn); 
    1391     }, 
    1392  
    1393     addCallback: function(fn) { 
    1394         this.callbacks.unshift(fn); 
    1395     }, 
    1396  
    1397     abort: function() { 
    1398         this.req.abort(); 
    1399     }, 
    1400  
    1401     addCallbacks: function(fn1, fn2) { 
    1402         this.addCallback(fn1); 
    1403         this.addErrback(fn2); 
    1404     }, 
    1405  
    1406     sendReq: function(data) { 
    1407         if(AJS.isObject(data)) { 
    1408             this.req.send(AJS.queryArguments(data)); 
    1409         } 
    1410         else if(AJS.isDefined(data)) 
    1411             this.req.send(data); 
    1412         else { 
    1413             this.req.send(""); 
    1414         } 
    1415     } 
    1416 }; 
    1417  
    1418 //Prevent memory-leaks 
    1419 AJS.addEventListener(window, 'unload', AJS._unloadListeners); 
    1420 AJS._createDomShortcuts() 
    1421 } 
    1422  
    1423 script_loaded = true; 
    1424  
    1425 /**** 
    1426 Last Modified: 13/05/07 00:25:28 
    1427  
    1428  GoogieSpell 
    1429      Google spell checker for your own web-apps :) 
     2 SpellCheck 
     3    jQuery'fied spell checker based on GoogieSpell 4.0 
    14304 Copyright Amir Salihefendic 2006 
     5 Copyright Aleksander Machniak 2009 
    14316     LICENSE 
    1432      GPL (see gpl.txt for more information) 
    1433      This basically means that you can't use this script with/in proprietary software! 
    1434      There is another license that permits you to use this script with proprietary software. Check out:... for more info. 
    1435      AUTHOR 
     7         GPL 
     8     AUTHORS 
    14369         4mir Salihefendic (http://amix.dk) - amix@amix.dk 
    1437  VERSION 
    1438      4.0 
    1439 ****/ 
    1440 var GOOGIE_CUR_LANG = null; 
    1441 var GOOGIE_DEFAULT_LANG = "en"; 
     10         Aleksander Machniak - alec [at] alec.pl 
     11*/ 
     12 
     13var SPELL_CUR_LANG = null; 
     14var GOOGIE_DEFAULT_LANG = 'en'; 
    144215 
    144316function GoogieSpell(img_dir, server_url) { 
    1444     var cookie_value; 
    1445     var lang; 
    1446     cookie_value = getCookie('language'); 
    1447  
    1448     if(cookie_value != null) 
    1449         GOOGIE_CUR_LANG = cookie_value; 
    1450     else 
    1451         GOOGIE_CUR_LANG = GOOGIE_DEFAULT_LANG; 
     17    var ref = this; 
     18 
     19    this.array_keys = function(arr) { 
     20        var res = []; 
     21        for (var key in arr) { res.push([key]); } 
     22        return res; 
     23    } 
     24     
     25    var cookie_value = getCookie('language'); 
     26    GOOGIE_CUR_LANG = cookie_value != null ? cookie_value : GOOGIE_DEFAULT_LANG; 
    145227 
    145328    this.img_dir = img_dir; 
    145429    this.server_url = server_url; 
    145530 
    1456     this.org_lang_to_word = {"da": "Dansk", "de": "Deutsch", "en": "English", 
    1457                                              "es": "Espa&#241;ol", "fr": "Fran&#231;ais", "it": "Italiano",  
    1458                                              "nl": "Nederlands", "pl": "Polski", "pt": "Portugu&#234;s", 
    1459                                              "fi": "Suomi", "sv": "Svenska"}; 
     31    this.org_lang_to_word = { 
     32        "da": "Dansk", "de": "Deutsch", "en": "English", 
     33        "es": "Espa&#241;ol", "fr": "Fran&#231;ais", "it": "Italiano",  
     34        "nl": "Nederlands", "pl": "Polski", "pt": "Portugu&#234;s", 
     35        "fi": "Suomi", "sv": "Svenska" 
     36    }; 
    146037    this.lang_to_word = this.org_lang_to_word; 
    1461     this.langlist_codes = AJS.keys(this.lang_to_word); 
    1462  
     38    this.langlist_codes = this.array_keys(this.lang_to_word); 
    146339    this.show_change_lang_pic = true; 
    1464     this.change_lang_pic_placement = "left"; 
    1465  
     40    this.change_lang_pic_placement = 'right'; 
    146641    this.report_state_change = true; 
    146742 
     
    147651    this.lang_no_suggestions = "No suggestions"; 
    147752     
    1478     this.show_spell_img = false;  // modified by roundcube 
     53    this.show_spell_img = false; // roundcube mod. 
    147954    this.decoration = true; 
    148055    this.use_close_btn = true; 
     
    150580    this.cnt_errors = 0; 
    150681    this.cnt_errors_fixed = 0; 
    1507  
     82     
    150883    //Set document on click to hide the language and error menu 
    1509     var fn = function(e) { 
    1510         var elm = AJS.getEventElm(e); 
    1511         if(elm.googie_action_btn != "1" && this.isLangWindowShown()) 
    1512             this.hideLangWindow(); 
    1513         if(elm.googie_action_btn != "1" && this.isErrorWindowShown()) 
    1514             this.hideErrorWindow(); 
    1515     }; 
    1516     AJS.AEV(document, "click", AJS.$b(fn, this)); 
    1517 } 
    1518  
    1519 GoogieSpell.prototype.decorateTextarea = function(id) { 
    1520     if(typeof(id) == "string") 
    1521         this.text_area = AJS.$(id); 
    1522     else 
    1523         this.text_area = id; 
    1524  
    1525     var r_width, r_height; 
    1526  
    1527     if(this.text_area != null) { 
    1528         if(!AJS.isDefined(this.spell_container) && this.decoration) { 
    1529             var table = AJS.TABLE(); 
    1530             var tbody = AJS.TBODY(); 
    1531             var tr = AJS.TR(); 
    1532             if(AJS.isDefined(this.force_width)) 
    1533                 r_width = this.force_width; 
    1534             else 
    1535                 r_width = this.text_area.offsetWidth + "px"; 
    1536  
    1537             if(AJS.isDefined(this.force_height)) 
    1538                 r_height = this.force_height; 
    1539             else 
    1540                 r_height = ""; 
    1541  
    1542             var spell_container = AJS.TD(); 
     84    $(document).bind('click', function(e) { 
     85        if($(e.target).attr('googie_action_btn') != '1' && ref.isLangWindowShown()) 
     86            ref.hideLangWindow(); 
     87        if($(e.target).attr('googie_action_btn') != '1' && ref.isErrorWindowShown()) 
     88            ref.hideErrorWindow(); 
     89    }); 
     90 
     91 
     92this.decorateTextarea = function(id) { 
     93    this.text_area = typeof(id) == 'string' ? document.getElementById(id) : id; 
     94 
     95    if (this.text_area) { 
     96        if (!this.spell_container && this.decoration) { 
     97            var table = document.createElement('TABLE'); 
     98            var tbody = document.createElement('TBODY'); 
     99            var tr = document.createElement('TR'); 
     100            var spell_container = document.createElement('TD'); 
     101 
     102            var r_width = this.isDefined(this.force_width) ? this.force_width : this.text_area.offsetWidth; 
     103            var r_height = this.isDefined(this.force_height) ? this.force_height : 16; 
     104 
     105            tr.appendChild(spell_container); 
     106            tbody.appendChild(tr); 
     107            $(table).append(tbody).insertBefore(this.text_area).width('100%').height(r_height); 
     108            $(spell_container).height(r_height).width(r_width).css('text-align', 'right'); 
     109 
    1543110            this.spell_container = spell_container; 
    1544  
    1545             tr.appendChild(spell_container); 
    1546  
    1547             tbody.appendChild(tr); 
    1548             table.appendChild(tbody); 
    1549  
    1550             AJS.insertBefore(table, this.text_area); 
    1551  
    1552             //Set width 
    1553             AJS.setHeight(table, spell_container, r_height); 
    1554             AJS.setWidth(table, spell_container, '100%');  // modified by roundcube (old: r_width) 
    1555  
    1556             spell_container.style.textAlign = "right"; 
    1557111        } 
    1558112 
     
    1560114    } 
    1561115    else  
    1562         if(this.report_ta_not_found) 
    1563             alert("Text area not found"); 
     116        if (this.report_ta_not_found) 
     117            alert('Text area not found'); 
    1564118} 
    1565119 
     
    1567121// API Functions (the ones that you can call) 
    1568122///// 
    1569 GoogieSpell.prototype.setSpellContainer = function(elm) { 
    1570     this.spell_container = AJS.$(elm); 
    1571 } 
    1572  
    1573 GoogieSpell.prototype.setLanguages = function(lang_dict) { 
     123this.setSpellContainer = function(id) { 
     124    this.spell_container = typeof(id) == 'string' ? document.getElementById(id) : id; 
     125 
     126} 
     127 
     128this.setLanguages = function(lang_dict) { 
    1574129    this.lang_to_word = lang_dict; 
    1575     this.langlist_codes = AJS.keys(lang_dict); 
    1576 } 
    1577  
    1578 GoogieSpell.prototype.setForceWidthHeight = function(width, height) { 
    1579     /*** 
    1580         Set to null if you want to use one of them 
    1581     ***/ 
     130    this.langlist_codes = this.array_keys(lang_dict); 
     131} 
     132 
     133this.setCurrentLanguage = function(lan_code) { 
     134    GOOGIE_CUR_LANG = lan_code; 
     135 
     136    //Set cookie 
     137    var now = new Date(); 
     138    now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); 
     139    setCookie('language', lan_code, now); 
     140} 
     141 
     142this.setForceWidthHeight = function(width, height) { 
     143    // Set to null if you want to use one of them 
    1582144    this.force_width = width; 
    1583145    this.force_height = height; 
    1584146} 
    1585147 
    1586 GoogieSpell.prototype.setDecoration = function(bool) { 
     148this.setDecoration = function(bool) { 
    1587149    this.decoration = bool; 
    1588150} 
    1589151 
    1590 GoogieSpell.prototype.dontUseCloseButtons = function() { 
     152this.dontUseCloseButtons = function() { 
    1591153    this.use_close_btn = false; 
    1592154} 
    1593155 
    1594 GoogieSpell.prototype.appendNewMenuItem = function(name, call_back_fn, checker) { 
     156this.appendNewMenuItem = function(name, call_back_fn, checker) { 
    1595157    this.extra_menu_items.push([name, call_back_fn, checker]); 
    1596158} 
    1597159 
    1598 GoogieSpell.prototype.appendCustomMenuBuilder = function(eval, builder) { 
     160this.appendCustomMenuBuilder = function(eval, builder) { 
    1599161    this.custom_menu_builder.push([eval, builder]); 
    1600162} 
    1601163 
    1602 GoogieSpell.prototype.setFocus = function() { 
     164this.setFocus = function() { 
    1603165    try { 
    1604166        this.focus_link_b.focus(); 
     
    1611173} 
    1612174 
    1613 GoogieSpell.prototype.getValue = function(ta) { 
    1614     return ta.value; 
    1615 } 
    1616  
    1617 GoogieSpell.prototype.setValue = function(ta, value) { 
    1618     ta.value = value; 
    1619 } 
    1620  
    1621175 
    1622176////// 
    1623177// Set functions (internal) 
    1624178///// 
    1625 GoogieSpell.prototype.setStateChanged = function(current_state) { 
     179this.setStateChanged = function(current_state) { 
    1626180    this.state = current_state; 
    1627     if(this.spelling_state_observer != null && this.report_state_change) 
     181    if (this.spelling_state_observer != null && this.report_state_change) 
    1628182        this.spelling_state_observer(current_state, this); 
    1629183} 
    1630184 
    1631 GoogieSpell.prototype.setReportStateChange = function(bool) { 
     185this.setReportStateChange = function(bool) { 
    1632186    this.report_state_change = bool; 
    1633187} 
     
    1637191// Request functions 
    1638192///// 
    1639 GoogieSpell.prototype.getGoogleUrl = function() { 
     193this.getUrl = function() { 
    1640194    return this.server_url + GOOGIE_CUR_LANG; 
    1641195} 
    1642196 
    1643 GoogieSpell.escapeSepcial = function(val) { 
     197this.escapeSpecial = function(val) { 
    1644198    return val.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); 
    1645199} 
    1646200 
    1647 GoogieSpell.createXMLReq = function (text) { 
    1648     return '<?xml version="1.0" encoding="utf-8" ?><spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1"><text>' + text + '</text></spellrequest>'; 
    1649 } 
    1650  
    1651 GoogieSpell.prototype.spellCheck = function(ignore) { 
    1652     var me = this; 
    1653  
     201this.createXMLReq = function (text) { 
     202    return '<?xml version="1.0" encoding="utf-8" ?>' 
     203        + '<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">' 
     204        + '<text>' + text + '</text></spellrequest>'; 
     205} 
     206 
     207this.spellCheck = function(ignore) { 
    1654208    this.cnt_errors_fixed = 0; 
    1655209    this.cnt_errors = 0; 
    1656     this.setStateChanged("checking_spell"); 
    1657  
    1658     if(this.main_controller) 
     210    this.setStateChanged('checking_spell'); 
     211 
     212    if (this.main_controller) 
    1659213        this.appendIndicator(this.spell_span); 
    1660214 
    1661215    this.error_links = []; 
    1662216    this.ta_scroll_top = this.text_area.scrollTop; 
    1663  
    1664     try { this.hideLangWindow(); } 
    1665     catch(e) {} 
    1666  
    1667217    this.ignore = ignore; 
    1668  
    1669     if(this.getValue(this.text_area) == '' || ignore) { 
    1670         if(!me.custom_no_spelling_error) 
    1671             me.flashNoSpellingErrorState(); 
     218    this.hideLangWindow(); 
     219 
     220    if ($(this.text_area).val() == '' || ignore) { 
     221        if (!this.custom_no_spelling_error) 
     222            this.flashNoSpellingErrorState(); 
    1672223        else 
    1673             me.custom_no_spelling_error(me); 
    1674         me.removeIndicator(); 
    1675         return ; 
     224            this.custom_no_spelling_error(this); 
     225        this.removeIndicator(); 
     226        return; 
    1676227    } 
    1677228     
    1678229    this.createEditLayer(this.text_area.offsetWidth, this.text_area.offsetHeight); 
    1679  
    1680230    this.createErrorWindow(); 
    1681     AJS.getBody().appendChild(this.error_window); 
     231    $('body').append(this.error_window); 
    1682232 
    1683233    try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }  
    1684234    catch (e) { } 
    1685235 
    1686     if(this.main_controller) 
    1687         this.spell_span.onclick = null; 
    1688  
    1689     this.orginal_text = this.getValue(this.text_area); 
    1690  
    1691     //Create request 
    1692     var d = AJS.getRequest(this.getGoogleUrl()); 
    1693     var reqdone = function(res_txt) { 
    1694         var r_text = res_txt; 
    1695         me.results = me.parseResult(r_text); 
    1696  
    1697         if(r_text.match(/<c.*>/) != null) { 
    1698             //Before parsing be sure that errors were found 
    1699             me.showErrorsInIframe(); 
    1700             me.resumeEditingState(); 
    1701         } 
    1702         else { 
    1703             if(!me.custom_no_spelling_error) 
    1704                 me.flashNoSpellingErrorState(); 
    1705             else 
    1706                 me.custom_no_spelling_error(me); 
    1707         } 
    1708         me.removeIndicator(); 
    1709     }; 
    1710  
    1711     d.addCallback(reqdone); 
    1712     reqdone = null; 
    1713  
    1714     var reqfailed = function(res_txt, req) { 
    1715         if(me.custom_ajax_error) 
    1716             me.custom_ajax_error(req); 
    1717         else 
    1718             alert("An error was encountered on the server. Please try again later."); 
    1719  
    1720         if(me.main_controller) { 
    1721             AJS.removeElement(me.spell_span); 
    1722             me.removeIndicator(); 
    1723         } 
    1724         me.checkSpellingState(); 
    1725     }; 
    1726     d.addErrback(reqfailed); 
    1727     reqfailed = null; 
    1728  
    1729     var req_text = GoogieSpell.escapeSepcial(this.orginal_text); 
    1730     d.sendReq(GoogieSpell.createXMLReq(req_text)); 
     236    if (this.main_controller) 
     237        $(this.spell_span).unbind('click'); 
     238 
     239    this.orginal_text = $(this.text_area).val(); 
     240    var req_text = this.escapeSpecial(this.orginal_text); 
     241    var ref = this; 
     242 
     243    $.ajax({ type: 'POST', url: this.getUrl(), 
     244        data: this.createXMLReq(req_text), dataType: 'text', 
     245        error: function(o) { 
     246            if (ref.custom_ajax_error) 
     247                ref.custom_ajax_error(ref); 
     248            else 
     249                alert('An error was encountered on the server. Please try again later.'); 
     250            if (ref.main_controller) { 
     251                $(ref.spell_span).remove(); 
     252                ref.removeIndicator(); 
     253            } 
     254            ref.checkSpellingState(); 
     255        }, 
     256        success: function(data) { 
     257            var r_text = data; 
     258            ref.results = ref.parseResult(r_text); 
     259            if (r_text.match(/<c.*>/) != null) { 
     260                //Before parsing be sure that errors were found 
     261                ref.showErrorsInIframe(); 
     262                ref.resumeEditingState(); 
     263            } else { 
     264                if (!ref.custom_no_spelling_error) 
     265                    ref.flashNoSpellingErrorState(); 
     266                else 
     267                    ref.custom_no_spelling_error(ref); 
     268            } 
     269            ref.removeIndicator(); 
     270        } 
     271    }); 
    1731272} 
    1732273 
     
    1735276// Spell checking functions 
    1736277///// 
    1737 GoogieSpell.prototype.parseResult = function(r_text) { 
    1738     /*** 
    1739      Retunrs an array 
    1740      result[item] -> ['attrs'], ['suggestions'] 
    1741         ***/ 
     278this.parseResult = function(r_text) { 
     279    // Returns an array: result[item] -> ['attrs'], ['suggestions'] 
    1742280    var re_split_attr_c = /\w+="(\d+|true)"/g; 
    1743281    var re_split_text = /\t/g; 
     
    1746284    var results = new Array(); 
    1747285 
    1748     if(matched_c == null) 
     286    if (matched_c == null) 
    1749287        return results; 
    1750288     
    1751     for(var i=0; i < matched_c.length; i++) { 
     289    for (var i=0; i < matched_c.length; i++) { 
    1752290        var item = new Array(); 
    1753291        this.errorFound(); 
     
    1756294        item['attrs'] = new Array(); 
    1757295        var split_c = matched_c[i].match(re_split_attr_c); 
    1758         for(var j=0; j < split_c.length; j++) { 
     296        for (var j=0; j < split_c.length; j++) { 
    1759297            var c_attr = split_c[j].split(/=/); 
    1760298            var val = c_attr[1].replace(/"/g, ''); 
    1761             if(val != "true") 
    1762                 item['attrs'][c_attr[0]] = parseInt(val); 
    1763             else { 
    1764                 item['attrs'][c_attr[0]] = val; 
    1765             } 
     299            item['attrs'][c_attr[0]] = val != 'true' ? parseInt(val) : val; 
    1766300        } 
    1767301 
    1768302        //Get suggestions 
    1769303        item['suggestions'] = new Array(); 
    1770         var only_text = matched_c[i].replace(/<[^>]*>/g, ""); 
     304        var only_text = matched_c[i].replace(/<[^>]*>/g, ''); 
    1771305        var split_t = only_text.split(re_split_text); 
    1772         for(var k=0; k < split_t.length; k++) { 
    1773         if(split_t[k] != "") 
    1774             item['suggestions'].push(split_t[k]); 
    1775         } 
     306        for (var k=0; k < split_t.length; k++) { 
     307            if(split_t[k] != '') 
     308                item['suggestions'].push(split_t[k]); 
     309        } 
    1776310        results.push(item); 
    1777311    } 
     
    1779313} 
    1780314 
    1781 ////// 
    1782 // Counters 
    1783 ///// 
    1784 GoogieSpell.prototype.errorFixed = function() {  
    1785     this.cnt_errors_fixed++;  
    1786     if(this.all_errors_fixed_observer) 
    1787         if(this.cnt_errors_fixed == this.cnt_errors) { 
    1788             this.hideErrorWindow(); 
    1789             this.all_errors_fixed_observer(); 
    1790         } 
    1791 } 
    1792 GoogieSpell.prototype.errorFound = function() { this.cnt_errors++; } 
    1793315 
    1794316////// 
    1795317// Error menu functions 
    1796318///// 
    1797 GoogieSpell.prototype.createErrorWindow = function() { 
    1798     this.error_window = AJS.DIV(); 
    1799     this.error_window.className = "googie_window"; 
    1800     this.error_window.googie_action_btn = "1"; 
    1801 } 
    1802  
    1803 GoogieSpell.prototype.isErrorWindowShown = function() { 
    1804     return this.error_window != null && this.error_window.style.visibility == "visible"; 
    1805 } 
    1806  
    1807 GoogieSpell.prototype.hideErrorWindow = function() { 
    1808     try { 
    1809         this.error_window.style.visibility = "hidden"; 
    1810         if(this.error_window_iframe) 
    1811             this.error_window_iframe.style.visibility = "hidden"; 
    1812     } 
    1813     catch(e) {} 
    1814 } 
    1815  
    1816 GoogieSpell.prototype.updateOrginalText = function(offset, old_value, new_value, id) { 
     319this.createErrorWindow = function() { 
     320    this.error_window = document.createElement('DIV'); 
     321    $(this.error_window).addClass('googie_window').attr('googie_action_btn', '1'); 
     322} 
     323 
     324this.isErrorWindowShown = function() { 
     325    return $(this.error_window).is(':visible'); 
     326} 
     327 
     328this.hideErrorWindow = function() { 
     329    $(this.error_window).css('visibility', 'hidden'); 
     330    $(this.error_window_iframe).css('visibility', 'hidden'); 
     331} 
     332 
     333this.updateOrginalText = function(offset, old_value, new_value, id) { 
    1817334    var part_1 = this.orginal_text.substring(0, offset); 
    1818335    var part_2 = this.orginal_text.substring(offset+old_value.length); 
    1819336    this.orginal_text = part_1 + new_value + part_2; 
    1820     this.setValue(this.text_area, this.orginal_text); 
     337    $(this.text_area).val(this.orginal_text); 
    1821338    var add_2_offset = new_value.length - old_value.length; 
    1822     for(var j=0; j < this.results.length; j++) { 
     339    for (var j=0; j < this.results.length; j++) { 
    1823340        //Don't edit the offset of the current item 
    1824         if(j != id && j > id){ 
     341        if (j != id && j > id) 
    1825342            this.results[j]['attrs']['o'] += add_2_offset; 
    1826         } 
    1827     } 
    1828 } 
    1829  
    1830 GoogieSpell.prototype.saveOldValue = function(elm, old_value) { 
     343    } 
     344} 
     345 
     346this.saveOldValue = function(elm, old_value) { 
    1831347    elm.is_changed = true; 
    1832348    elm.old_value = old_value; 
    1833349} 
    1834350 
    1835 GoogieSpell.prototype.createListSeparator = function() { 
    1836     var e_col = AJS.TD(" "); 
    1837     e_col.googie_action_btn = "1"; 
    1838     e_col.style.cursor = "default"; 
    1839     e_col.style.fontSize = "3px"; 
    1840     e_col.style.borderTop = "1px solid #ccc"; 
    1841     e_col.style.paddingTop = "3px"; 
    1842  
    1843     return AJS.TR(e_col); 
    1844 } 
    1845  
    1846 GoogieSpell.prototype.correctError = function(id, elm, l_elm, /*optional*/ rm_pre_space) { 
     351this.createListSeparator = function() { 
     352    var td = document.createElement('TD'); 
     353    var tr = document.createElement('TR'); 
     354 
     355    $(td).html(' ').attr('googie_action_btn', '1') 
     356        .css({'cursor': 'default', 'font-size': '3px', 'border-top': '1px solid #ccc', 'padding-top': '3px'}); 
     357    tr.appendChild(td); 
     358 
     359    return tr; 
     360} 
     361 
     362this.correctError = function(id, elm, l_elm, rm_pre_space) { 
    1847363    var old_value = elm.innerHTML; 
    1848364    var new_value = l_elm.innerHTML; 
    1849365    var offset = this.results[id]['attrs']['o']; 
    1850366 
    1851     if(rm_pre_space) { 
     367    if (rm_pre_space) { 
    1852368        var pre_length = elm.previousSibling.innerHTML; 
    1853369        elm.previousSibling.innerHTML = pre_length.slice(0, pre_length.length-1); 
     
    1857373 
    1858374    this.hideErrorWindow(); 
    1859  
    1860375    this.updateOrginalText(offset, old_value, new_value, id); 
    1861376 
    1862     elm.innerHTML = new_value; 
    1863      
    1864     elm.style.color = "green"; 
    1865     elm.is_corrected = true; 
     377    $(elm).html(new_value).css('color', 'green').attr('is_corrected', true); 
    1866378 
    1867379    this.results[id]['attrs']['l'] = new_value.length; 
    1868380 
    1869     if(!AJS.isDefined(elm.old_value)) 
     381    if (!this.isDefined(elm.old_value)) 
    1870382        this.saveOldValue(elm, old_value); 
    1871383     
     
    1873385} 
    1874386 
    1875 GoogieSpell.prototype.showErrorWindow = function(elm, id) { 
    1876     if(this.show_menu_observer) 
     387this.showErrorWindow = function(elm, id) { 
     388    if (this.show_menu_observer) 
    1877389        this.show_menu_observer(this); 
    1878     var me = this; 
    1879  
    1880     var abs_pos = AJS.absolutePosition(elm); 
    1881     abs_pos.y -= this.edit_layer.scrollTop; 
    1882     this.error_window.style.visibility = "visible"; 
    1883  
    1884     AJS.setTop(this.error_window, (abs_pos.y+20)); 
    1885     AJS.setLeft(this.error_window, (abs_pos.x)); 
    1886  
    1887     this.error_window.innerHTML = ""; 
    1888  
    1889     var table = AJS.TABLE({'class': 'googie_list'}); 
    1890     table.googie_action_btn = "1"; 
    1891     var list = AJS.TBODY(); 
     390 
     391    var ref = this; 
     392    var pos = $(elm).offset(); 
     393    pos.top -= this.edit_layer.scrollTop; 
     394 
     395    $(this.error_window).css({'visibility': 'visible', 
     396        'top': (pos.top+20)+'px', 'left': (pos.left)+'px'}).html(''); 
     397 
     398    var table = document.createElement('TABLE'); 
     399    var list = document.createElement('TBODY'); 
     400 
     401    $(table).addClass('googie_list').attr('googie_action_btn', '1'); 
    1892402 
    1893403    //Check if we should use custom menu builder, if not we use the default 
    1894404    var changed = false; 
    1895     if(this.custom_menu_builder != []) { 
    1896         for(var k=0; k<this.custom_menu_builder.length; k++) { 
     405    if (this.custom_menu_builder != []) { 
     406        for (var k=0; k<this.custom_menu_builder.length; k++) { 
    1897407            var eb = this.custom_menu_builder[k]; 
    1898408            if(eb[0]((this.results[id]))){ 
     
    1902412        } 
    1903413    } 
    1904     if(!changed) { 
     414    if (!changed) { 
    1905415        //Build up the result list 
    1906416        var suggestions = this.results[id]['suggestions']; 
     
    1908418        var len = this.results[id]['attrs']['l']; 
    1909419 
    1910         if(suggestions.length == 0) { 
    1911             var row = AJS.TR(); 
    1912             var item = AJS.TD({'style': 'cursor: default;'}); 
    1913             var dummy = AJS.SPAN(); 
    1914             dummy.innerHTML = this.lang_no_suggestions; 
    1915             AJS.ACN(item, AJS.TN(dummy.innerHTML)); 
    1916             item.googie_action_btn = "1"; 
     420        if (suggestions.length == 0) { 
     421            var row = document.createElement('TR'); 
     422            var item = document.createElement('TD'); 
     423            var dummy = document.createElement('SPAN'); 
     424 
     425            $(dummy).text(this.lang_no_suggestions); 
     426            $(item).attr('googie_action_btn', '1').css('cursor', 'default'); 
     427 
     428            item.appendChild(dummy); 
    1917429            row.appendChild(item); 
    1918430            list.appendChild(row); 
    1919431        } 
    1920432 
    1921         for(i=0; i < suggestions.length; i++) { 
    1922             var row = AJS.TR(); 
    1923             var item = AJS.TD(); 
    1924             var dummy = AJS.SPAN(); 
    1925             dummy.innerHTML = suggestions[i]; 
    1926             item.appendChild(AJS.TN(dummy.innerHTML)); 
     433        for (i=0; i < suggestions.length; i++) { 
     434            var row = document.createElement('TR'); 
     435            var item = document.createElement('TD'); 
     436            var dummy = document.createElement('SPAN'); 
     437 
     438            $(dummy).html(suggestions[i]); 
    1927439             
    1928             var fn = function(e) { 
    1929                 var l_elm = AJS.getEventElm(e); 
    1930                 this.correctError(id, elm, l_elm); 
    1931             }; 
    1932  
    1933             AJS.AEV(item, "click", AJS.$b(fn, this)); 
    1934  
    1935             item.onmouseover = GoogieSpell.item_onmouseover; 
    1936             item.onmouseout = GoogieSpell.item_onmouseout; 
     440            $(item).bind('mouseover', this.item_onmouseover) 
     441                .bind('mouseout', this.item_onmouseout) 
     442                .bind('click', function(e) { ref.correctError(id, elm, e.target.firstChild) }); 
     443 
     444            item.appendChild(dummy); 
    1937445            row.appendChild(item); 
    1938446            list.appendChild(row); 
     
    1940448 
    1941449        //The element is changed, append the revert 
    1942         if(elm.is_changed && elm.innerHTML != elm.old_value) { 
     450        if (elm.is_changed && elm.innerHTML != elm.old_value) { 
    1943451            var old_value = elm.old_value; 
    1944             var revert_row = AJS.TR(); 
    1945             var revert = AJS.TD(); 
    1946  
    1947             revert.onmouseover = GoogieSpell.item_onmouseover; 
    1948             revert.onmouseout = GoogieSpell.item_onmouseout; 
    1949             var rev_span = AJS.SPAN({'class': 'googie_list_revert'}); 
    1950             rev_span.innerHTML = this.lang_revert + " " + old_value; 
     452            var revert_row = document.createElement('TR'); 
     453            var revert = document.createElement('TD'); 
     454            var rev_span = document.createElement('SPAN'); 
     455             
     456            $(rev_span).addClass('googie_list_revert').html(this.lang_revert + ' ' + old_value); 
     457 
     458            $(revert).bind('mouseover', this.item_onmouseover) 
     459                .bind('mouseout', this.item_onmouseout) 
     460                .bind('click', function(e) { 
     461                    ref.updateOrginalText(offset, elm.innerHTML, old_value, id); 
     462                    $(elm).attr('is_corrected', true).css('color', '#b91414').html(old_value); 
     463                    ref.hideErrorWindow(); 
     464                }); 
     465 
    1951466            revert.appendChild(rev_span); 
    1952  
    1953             var fn = function(e) {  
    1954                 this.updateOrginalText(offset, elm.innerHTML, old_value, id); 
    1955                 elm.is_corrected = true; 
    1956                 elm.style.color = "#b91414"; 
    1957                 elm.innerHTML = old_value; 
    1958                 this.hideErrorWindow(); 
    1959             }; 
    1960             AJS.AEV(revert, "click", AJS.$b(fn, this)); 
    1961  
    1962467            revert_row.appendChild(revert); 
    1963468            list.appendChild(revert_row); 
     
    1965470         
    1966471        //Append the edit box 
    1967         var edit_row = AJS.TR(); 
    1968         var edit = AJS.TD({'style': 'cursor: default'}); 
    1969  
    1970         var edit_input = AJS.INPUT({'style': 'width: 120px; margin:0; padding:0', 'value': elm.innerHTML}); 
    1971         edit_input.googie_action_btn = "1"; 
     472        var edit_row = document.createElement('TR'); 
     473        var edit = document.createElement('TD'); 
     474        var edit_input = document.createElement('INPUT'); 
     475        var ok_pic = document.createElement('IMG'); 
     476        var edit_form = document.createElement('FORM'); 
    1972477 
    1973478        var onsub = function () { 
    1974             if(edit_input.value != "") { 
    1975                 if(!AJS.isDefined(elm.old_value)) 
    1976                     this.saveOldValue(elm, elm.innerHTML); 
    1977  
    1978                 this.updateOrginalText(offset, elm.innerHTML, edit_input.value, id); 
    1979                 elm.style.color = "green" 
    1980                 elm.is_corrected = true; 
    1981                 elm.innerHTML = edit_input.value; 
    1982                  
    1983                 this.hideErrorWindow(); 
     479            if (edit_input.value != '') { 
     480                if (!ref.isDefined(elm.old_value)) 
     481                    ref.saveOldValue(elm, elm.innerHTML); 
     482 
     483                ref.updateOrginalText(offset, elm.innerHTML, edit_input.value, id); 
     484                $(elm).attr('is_corrected', true).css('color', 'green').html(edit_input.value); 
     485                ref.hideErrorWindow(); 
    1984486            } 
    1985487            return false; 
    1986488        }; 
    1987         onsub = AJS.$b(onsub, this); 
     489 
     490        $(edit_input).width(120).css({'margin': 0, 'padding': 0}); 
     491        $(edit_input).val(elm.innerHTML).attr('googie_action_btn', '1'); 
     492        $(edit).css('cursor', 'default').attr('googie_action_btn', '1'); 
     493 
     494        $(ok_pic).attr('src', this.img_dir + 'ok.gif') 
     495            .width(32).height(16) 
     496            .css({'cursor': 'pointer', 'margin-left': '2px', 'margin-right': '2px'}) 
     497            .bind('click', onsub); 
     498 
     499        $(edit_form).attr('googie_action_btn', '1') 
     500            .css({'margin': 0, 'padding': 0, 'cursor': 'default', 'white-space': 'nowrap'}) 
     501            .bind('submit', onsub); 
    1988502         
    1989         var ok_pic = AJS.IMG({'src': this.img_dir + "ok.gif", 'style': 'width: 32px; height: 16px; margin-left: 2px; margin-right: 2px; cursor: pointer;'}); 
    1990         var edit_form = AJS.FORM({'style': 'margin: 0; padding: 0; cursor: default;'}, edit_input, ok_pic); 
    1991  
    1992         edit_form.googie_action_btn = "1"; 
    1993         edit.googie_action_btn = "1"; 
    1994  
    1995         AJS.AEV(edit_form, "submit", onsub); 
    1996         AJS.AEV(ok_pic, "click", onsub); 
    1997          
     503        edit_form.appendChild(edit_input); 
     504        edit_form.appendChild(ok_pic); 
    1998505        edit.appendChild(edit_form); 
    1999506        edit_row.appendChild(edit); 
     
    2001508 
    2002509        //Append extra menu items 
    2003         if(this.extra_menu_items.length > 0) 
    2004             AJS.ACN(list, this.createListSeparator()); 
    2005  
     510        if (this.extra_menu_items.length > 0) 
     511            list.appendChild(this.createListSeparator()); 
     512         
    2006513        var loop = function(i) { 
    2007                 if(i < me.extra_menu_items.length) { 
    2008                     var e_elm = me.extra_menu_items[i]; 
    2009  
    2010                     if(!e_elm[2] || e_elm[2](elm, me)) { 
    2011                         var e_row = AJS.TR(); 
    2012                         var e_col = AJS.TD(e_elm[0]); 
    2013  
    2014                         e_col.onmouseover = GoogieSpell.item_onmouseover; 
    2015                         e_col.onmouseout = GoogieSpell.item_onmouseout; 
    2016  
    2017                         var fn = function() { 
    2018                             return e_elm[1](elm, me); 
    2019                         }; 
    2020                         AJS.AEV(e_col, "click", fn); 
    2021  
    2022                         AJS.ACN(e_row, e_col); 
    2023                         AJS.ACN(list, e_row); 
    2024  
     514                if (i < ref.extra_menu_items.length) { 
     515                    var e_elm = ref.extra_menu_items[i]; 
     516 
     517                    if (!e_elm[2] || e_elm[2](elm, ref)) { 
     518                        var e_row = document.createElement('TR'); 
     519                        var e_col = document.createElement('TD'); 
     520 
     521                        $(e_col).html(e_elm[0]) 
     522                            .bind('mouseover', ref.item_onmouseover) 
     523                            .bind('mouseout', ref.item_onmouseout) 
     524                            .bind('click', function() { return e_elm[1](elm, ref) }); 
     525                         
     526                        e_row.appendChild(e_col); 
     527                        list.appendChild(e_row); 
    2025528                    } 
    2026529                    loop(i+1); 
    2027530                } 
    2028531        } 
     532         
    2029533        loop(0); 
    2030534        loop = null; 
    2031535 
    2032536        //Close button 
    2033         if(this.use_close_btn) { 
    2034             AJS.ACN(list, this.createCloseButton(this.hideErrorWindow)); 
     537        if (this.use_close_btn) { 
     538            list.appendChild(this.createCloseButton(this.hideErrorWindow)); 
    2035539        } 
    2036540    } 
     
    2040544 
    2041545    //Dummy for IE - dropdown bug fix 
    2042     if(AJS.isIe() && !this.error_window_iframe) { 
    2043         var iframe = AJS.IFRAME({'style': 'position: absolute; z-index: 0;'}); 
    2044         AJS.ACN(AJS.getBody(), iframe); 
    2045         this.error_window_iframe = iframe; 
    2046     } 
    2047     if(AJS.isIe()) { 
    2048         var iframe = this.error_window_iframe; 
    2049         AJS.setTop(iframe, this.error_window.offsetTop); 
    2050         AJS.setLeft(iframe, this.error_window.offsetLeft); 
    2051  
    2052         AJS.setWidth(iframe, this.error_window.offsetWidth); 
    2053         AJS.setHeight(iframe, this.error_window.offsetHeight); 
    2054  
    2055         iframe.style.visibility = "visible"; 
    2056     } 
    2057  
    2058     //Set focus on the last element 
    2059     var link = this.createFocusLink('link'); 
    2060     list.appendChild(AJS.TR(AJS.TD({'style': 'text-align: right; font-size: 1px; height: 1px; margin: 0; padding: 0;'}, link))); 
    2061     link.focus(); 
     546    if ($.browser.msie) { 
     547        if (!this.error_window_iframe) { 
     548            var iframe = $('<iframe>').css('position', 'absolute').css('z-index', 0); 
     549            $('body').append(iframe); 
     550            this.error_window_iframe = iframe; 
     551        } 
     552         
     553        $(this.error_window_iframe).css({'visibility': 'visible', 
     554            'top': this.error_window.offsetTop, 'left': this.error_window.offsetLeft, 
     555            'width': this.error_window.offsetWidth, 'height': this.error_window.offsetHeight}); 
     556    } 
    2062557} 
    2063558 
     
    2066561// Edit layer (the layer where the suggestions are stored) 
    2067562////// 
    2068 GoogieSpell.prototype.createEditLayer = function(width, height) { 
    2069     this.edit_layer = AJS.DIV({'class': 'googie_edit_layer'}); 
    2070  
    2071     //Set the style so it looks like edit areas 
    2072     this.edit_layer.className = this.text_area.className; 
    2073     this.edit_layer.style.border = "1px solid #999"; 
    2074     this.edit_layer.style.backgroundColor = "#F1EDFE";  // modified by roundcube 
    2075     this.edit_layer.style.padding = "3px"; 
    2076     this.edit_layer.style.margin = "0px"; 
    2077  
    2078     AJS.setWidth(this.edit_layer, (width-8)); 
    2079  
    2080     if(AJS.nodeName(this.text_area) != "input" || this.getValue(this.text_area) == "") { 
    2081         this.edit_layer.style.overflow = "auto"; 
    2082         AJS.setHeight(this.edit_layer, (height-6)); 
    2083     } 
    2084     else { 
    2085         this.edit_layer.style.overflow = "hidden"; 
    2086     } 
    2087  
    2088     if(this.edit_layer_dbl_click) { 
    2089         var me = this; 
    2090         var fn = function(e) { 
    2091             if(AJS.getEventElm(e).className != "googie_link" && !me.isErrorWindowShown()) { 
    2092                 me.resumeEditing(); 
     563this.createEditLayer = function(width, height) { 
     564    this.edit_layer = document.createElement('DIV'); 
     565    $(this.edit_layer).addClass('googie_edit_layer').width(width-10).height(height); 
     566 
     567    if (this.text_area.nodeName != 'INPUT' || $(this.text_area).val() == '') { 
     568        $(this.edit_layer).css('overflow', 'auto').height(height-4); 
     569    } else { 
     570        $(this.edit_layer).css('overflow', 'hidden'); 
     571    } 
     572 
     573    var ref = this; 
     574    if (this.edit_layer_dbl_click) { 
     575        $(this.edit_layer).bind('click', function(e) { 
     576            if (e.target.className != 'googie_link' && !ref.isErrorWindowShown()) { 
     577                ref.resumeEditing(); 
    2093578                var fn1 = function() { 
    2094                     me.text_area.focus(); 
     579                    $(ref.text_area).focus(); 
    2095580                    fn1 = null; 
    2096581                }; 
    2097                 AJS.callLater(fn1, 10); 
     582                window.setTimeout(fn1, 10); 
    2098583            } 
    2099584            return false; 
    2100         }; 
    2101         this.edit_layer.ondblclick = fn; 
    2102         fn = null; 
    2103     } 
    2104 } 
    2105  
    2106 GoogieSpell.prototype.resumeEditing = function() { 
    2107     this.setStateChanged("spell_check"); 
    2108     this.switch_lan_pic.style.display = "inline"; 
    2109  
    2110     if(this.edit_layer) 
     585        }); 
     586    } 
     587} 
     588 
     589this.resumeEditing = function() { 
     590    this.setStateChanged('ready'); 
     591 
     592    if (this.edit_layer) 
    2111593        this.el_scroll_top = this.edit_layer.scrollTop; 
    2112594 
    2113595    this.hideErrorWindow(); 
    2114596 
    2115     if(this.main_controller) 
    2116         this.spell_span.className = "googie_no_style"; 
    2117  
    2118     if(!this.ignore) { 
    2119         //Remove the EDIT_LAYER 
    2120         try { 
    2121             this.edit_layer.parentNode.removeChild(this.edit_layer); 
    2122             if(this.use_focus) { 
    2123                 AJS.removeElement(this.focus_link_t); 
    2124                 AJS.removeElement(this.focus_link_b); 
    2125             } 
    2126         } 
    2127         catch(e) { 
    2128         } 
    2129  
    2130         AJS.showElement(this.text_area); 
    2131  
    2132         if(this.el_scroll_top != undefined) 
     597    if (this.main_controller) 
     598        $(this.spell_span).removeClass().addClass('googie_no_style'); 
     599 
     600    if (!this.ignore) { 
     601        if (this.use_focus) { 
     602            $(this.focus_link_t).remove(); 
     603            $(this.focus_link_b).remove(); 
     604        } 
     605 
     606        $(this.edit_layer).remove(); 
     607        $(this.text_area).show(); 
     608 
     609        if (this.el_scroll_top != undefined) 
    2133610            this.text_area.scrollTop = this.el_scroll_top; 
    2134611    } 
    2135  
    2136612    this.checkSpellingState(false); 
    2137613} 
    2138614 
    2139 GoogieSpell.prototype.createErrorLink = function(text, id) { 
    2140     var elm = AJS.SPAN({'class': 'googie_link'}); 
    2141     var me = this; 
     615this.createErrorLink = function(text, id) { 
     616    var elm = document.createElement('SPAN'); 
     617    var ref = this; 
    2142618    var d = function (e) { 
    2143         me.showErrorWindow(elm, id); 
    2144         d = null; 
    2145         return false; 
     619            ref.showErrorWindow(elm, id); 
     620            d = null; 
     621            return false; 
    2146622    }; 
    2147     AJS.AEV(elm, "click", d); 
    2148  
    2149     elm.googie_action_btn = "1"; 
    2150     elm.g_id = id; 
    2151     elm.is_corrected = false; 
    2152     elm.oncontextmenu = d; 
    2153     elm.innerHTML = text; 
     623     
     624    $(elm).html(text).addClass('googie_link').bind('click', d) 
     625        .attr({'googie_action_btn' : '1', 'g_id' : id, 'is_corrected' : false}); 
     626 
    2154627    return elm; 
    2155628} 
    2156629 
    2157 GoogieSpell.createPart = function(txt_part) { 
    2158     if(txt_part == " ") 
    2159         return AJS.TN(" "); 
    2160     var result = AJS.SPAN(); 
    2161  
    2162     var is_first = true; 
    2163     var is_safari = (navigator.userAgent.toLowerCase().indexOf("safari") != -1); 
    2164  
    2165     var part = AJS.SPAN(); 
    2166     txt_part = GoogieSpell.escapeSepcial(txt_part); 
     630this.createPart = function(txt_part) { 
     631    if (txt_part == " ") 
     632        return document.createTextNode(" "); 
     633 
     634    txt_part = this.escapeSpecial(txt_part); 
    2167635    txt_part = txt_part.replace(/\n/g, "<br>"); 
    2168636    txt_part = txt_part.replace(/    /g, " &nbsp;"); 
     
    2170638    txt_part = txt_part.replace(/ $/g, "&nbsp;"); 
    2171639     
    2172     part.innerHTML = txt_part; 
    2173  
    2174     return part; 
    2175 } 
    2176  
    2177 GoogieSpell.prototype.showErrorsInIframe = function() { 
    2178     var output = AJS.DIV(); 
    2179     output.style.textAlign = "left"; 
     640    var span = document.createElement('SPAN'); 
     641    $(span).html(txt_part); 
     642    return span; 
     643} 
     644 
     645this.showErrorsInIframe = function() { 
     646    var output = document.createElement('DIV') 
    2180647    var pointer = 0; 
    2181648    var results = this.results; 
    2182649 
    2183     if(results.length > 0) { 
    2184         for(var i=0; i < results.length; i++) { 
     650    if (results.length > 0) { 
     651        for (var i=0; i < results.length; i++) { 
    2185652            var offset = results[i]['attrs']['o']; 
    2186653            var len = results[i]['attrs']['l']; 
    2187              
    2188654            var part_1_text = this.orginal_text.substring(pointer, offset); 
    2189             var part_1 = GoogieSpell.createPart(part_1_text); 
     655            var part_1 = this.createPart(part_1_text); 
     656     
    2190657            output.appendChild(part_1); 
    2191658            pointer += offset - pointer; 
     
    2199666        //Insert the rest of the orginal text 
    2200667        var part_2_text = this.orginal_text.substr(pointer, this.orginal_text.length); 
    2201  
    2202         var part_2 = GoogieSpell.createPart(part_2_text); 
     668        var part_2 = this.createPart(part_2_text); 
     669 
    2203670        output.appendChild(part_2); 
    2204671    } 
     
    2206673        output.innerHTML = this.orginal_text; 
    2207674 
     675    $(output).css('text-align', 'left'); 
     676 
    2208677    var me = this; 
    2209     if(this.custom_item_evaulator) 
    2210         AJS.map(this.error_links, function(elm){me.custom_item_evaulator(me, elm)}); 
     678    if (this.custom_item_evaulator) 
     679        $.map(this.error_links, function(elm){me.custom_item_evaulator(me, elm)}); 
    2211680     
    2212     AJS.ACN(this.edit_layer, output); 
    2213  
    2214     //Hide text area 
    2215     this.text_area_bottom = this.text_area.offsetTop + this.text_area.offsetHeight; 
    2216  
    2217     AJS.hideElement(this.text_area); 
    2218  
    2219     AJS.insertBefore(this.edit_layer, this.text_area); 
    2220  
    2221     if(this.use_focus) { 
     681    $(this.edit_layer).append(output); 
     682 
     683    //Hide text area and show edit layer 
     684    $(this.text_area).hide(); 
     685    $(this.edit_layer).insertBefore(this.text_area); 
     686 
     687    if (this.use_focus) { 
    2222688        this.focus_link_t = this.createFocusLink('focus_t'); 
    2223689        this.focus_link_b = this.createFocusLink('focus_b'); 
    2224690 
    2225         AJS.insertBefore(this.focus_link_t, this.edit_layer); 
    2226         AJS.insertAfter(this.focus_link_b, this.edit_layer); 
    2227     } 
    2228  
    2229     this.edit_layer.scrollTop = this.ta_scroll_top; 
     691        $(this.focus_link_t).insertBefore(this.edit_layer); 
     692        $(this.focus_link_b).insertAfter(this.edit_layer); 
     693    } 
     694 
     695//    this.edit_layer.scrollTop = this.ta_scroll_top; 
    2230696} 
    2231697 
     
    2234700// Choose language menu 
    2235701////// 
    2236 GoogieSpell.prototype.createLangWindow = function() { 
    2237     this.language_window = AJS.DIV({'class': 'googie_window'}); 
    2238     AJS.setWidth(this.language_window, 100); 
    2239  
    2240     this.language_window.googie_action_btn = "1"; 
     702this.createLangWindow = function() { 
     703    this.language_window = document.createElement('DIV'); 
     704    $(this.language_window).addClass('googie_window') 
     705        .width(100).attr('googie_action_btn', '1'); 
    2241706 
    2242707    //Build up the result list 
    2243     var table = AJS.TABLE({'class': 'googie_list'}); 
    2244     AJS.setWidth(table, "100%"); 
    2245     var list = AJS.TBODY(); 
    2246  
     708    var table = document.createElement('TABLE'); 
     709    var list = document.createElement('TBODY'); 
     710    var ref = this; 
     711 
     712    $(table).addClass('googie_list').width('100%'); 
    2247713    this.lang_elms = new Array(); 
    2248714 
    2249     for(i=0; i < this.langlist_codes.length; i++) { 
    2250         var row = AJS.TR(); 
    2251         var item = AJS.TD(); 
    2252         item.googieId = this.langlist_codes[i]; 
     715    for (i=0; i < this.langlist_codes.length; i++) { 
     716        var row = document.createElement('TR'); 
     717        var item = document.createElement('TD'); 
     718        var span = document.createElement('SPAN'); 
     719         
     720        $(span).text(this.lang_to_word[this.langlist_codes[i]]); 
    2253721        this.lang_elms.push(item); 
    2254         var lang_span = AJS.SPAN(); 
    2255         lang_span.innerHTML = this.lang_to_word[this.langlist_codes[i]]; 
    2256         item.appendChild(AJS.TN(lang_span.innerHTML)); 
    2257  
    2258         var fn = function(e) { 
    2259             var elm = AJS.getEventElm(e); 
    2260             this.deHighlightCurSel(); 
    2261  
    2262             this.setCurrentLanguage(elm.googieId); 
    2263  
    2264             if(this.lang_state_observer != null) { 
    2265                 this.lang_state_observer(); 
    2266             } 
    2267  
    2268             this.highlightCurSel(); 
    2269             this.hideLangWindow(); 
    2270         }; 
    2271         AJS.AEV(item, "click", AJS.$b(fn, this)); 
    2272  
    2273         item.onmouseover = function(e) {  
    2274             var i_it = AJS.getEventElm(e); 
    2275             if(i_it.className != "googie_list_selected") 
    2276                 i_it.className = "googie_list_onhover"; 
    2277         }; 
    2278         item.onmouseout = function(e) {  
    2279             var i_it = AJS.getEventElm(e); 
    2280             if(i_it.className != "googie_list_selected") 
    2281                 i_it.className = "googie_list_onout";  
    2282         }; 
    2283  
     722 
     723        $(item).attr('googieId', this.langlist_codes[i]) 
     724            .bind('click', function(e) { 
     725                ref.deHighlightCurSel(); 
     726                ref.setCurrentLanguage($(this).attr('googieId')); 
     727 
     728                if (ref.lang_state_observer != null) { 
     729                    ref.lang_state_observer(); 
     730                } 
     731 
     732                ref.highlightCurSel(); 
     733                ref.hideLangWindow(); 
     734            }) 
     735            .bind('mouseover', function(e) {  
     736                if (this.className != "googie_list_selected") 
     737                    this.className = "googie_list_onhover"; 
     738            }) 
     739            .bind('mouseout', function(e) {  
     740                if (this.className != "googie_list_selected") 
     741                    this.className = "googie_list_onout";  
     742            }); 
     743 
     744        item.appendChild(span); 
    2284745        row.appendChild(item); 
    2285746        list.appendChild(row); 
     
    2287748 
    2288749    //Close button 
    2289     if(this.use_close_btn) { 
    2290         list.appendChild(this.createCloseButton(this.hideLangWindow)); 
     750    if (this.use_close_btn) { 
     751        list.appendChild(this.createCloseButton(function () { ref.hideLangWindow.apply(ref) })); 
    2291752    } 
    2292753 
     
    2297758} 
    2298759 
    2299 GoogieSpell.prototype.setCurrentLanguage = function(lan_code) { 
    2300     GOOGIE_CUR_LANG = lan_code; 
    2301  
    2302     //Set cookie 
    2303     var now = new Date(); 
    2304     now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); 
    2305     setCookie('language', lan_code, now); 
    2306 } 
    2307  
    2308 GoogieSpell.prototype.isLangWindowShown = function() { 
    2309     return this.language_window != null && this.language_window.style.visibility == "visible"; 
    2310 } 
    2311  
    2312 GoogieSpell.prototype.hideLangWindow = function() { 
    2313     try { 
    2314         this.language_window.style.visibility = "hidden"; 
    2315         this.switch_lan_pic.className = "googie_lang_3d_on"; 
    2316     } 
    2317     catch(e) {} 
    2318 } 
    2319  
    2320 GoogieSpell.prototype.deHighlightCurSel = function() { 
    2321     this.lang_cur_elm.className = "googie_list_onout"; 
    2322 } 
    2323  
    2324 GoogieSpell.prototype.highlightCurSel = function() { 
    2325     if(GOOGIE_CUR_LANG == null) 
     760this.isLangWindowShown = function() { 
     761    return $(this.language_window).is(':hidden'); 
     762} 
     763 
     764this.hideLangWindow = function() { 
     765    $(this.language_window).css('visibility', 'hidden'); 
     766    $(this.switch_lan_pic).removeClass().addClass('googie_lang_3d_on'); 
     767} 
     768 
     769this.deHighlightCurSel = function() { 
     770    $(this.lang_cur_elm).removeClass().addClass('googie_list_onout'); 
     771} 
     772 
     773this.highlightCurSel = function() { 
     774    if (GOOGIE_CUR_LANG == null) 
    2326775        GOOGIE_CUR_LANG = GOOGIE_DEFAULT_LANG; 
    2327     for(var i=0; i < this.lang_elms.length; i++) { 
    2328         if(this.lang_elms[i].googieId == GOOGIE_CUR_LANG) { 
     776    for (var i=0; i < this.lang_elms.length; i++) { 
     777        if ($(this.lang_elms[i]).attr('googieId') == GOOGIE_CUR_LANG) { 
    2329778            this.lang_elms[i].className = "googie_list_selected"; 
    2330779            this.lang_cur_elm = this.lang_elms[i]; 
     
    2336785} 
    2337786 
    2338 GoogieSpell.prototype.showLangWindow = function(elm, ofst_top, ofst_left) { 
    2339     if(this.show_menu_observer) 
     787this.showLangWindow = function(elm) { 
     788    if (this.show_menu_observer) 
    2340789        this.show_menu_observer(this); 
    2341     if(!AJS.isDefined(ofst_top)) 
    2342         ofst_top = 18;  // modified by roundcube 
    2343     if(!AJS.isDefined(ofst_left)) 
    2344         ofst_left = 22; // modified by roundcube 
    2345790 
    2346791    this.createLangWindow(); 
    2347     AJS.getBody().appendChild(this.language_window); 
    2348  
    2349     var abs_pos = AJS.absolutePosition(elm); 
    2350     AJS.showElement(this.language_window); 
    2351     AJS.setTop(this.language_window, (abs_pos.y+ofst_top)); 
    2352     AJS.setLeft(this.language_window, (abs_pos.x+ofst_left-this.language_window.offsetWidth)); 
     792    $('body').append(this.language_window); 
     793 
     794    var pos = $(elm).offset(); 
     795    var top = pos.top + $(elm).height(); 
     796    var left = this.change_lang_pic_placement == 'right' ?  
     797        pos.left - 100 + $(elm).width() : pos.left + $(elm).width(); 
     798 
     799    $(this.language_window).css({'visibility': 'visible', 'top' : top+'px','left' : left+'px'}); 
    2353800 
    2354801    this.highlightCurSel(); 
    2355     this.language_window.style.visibility = "visible"; 
    2356 } 
    2357  
    2358 GoogieSpell.prototype.createChangeLangPic = function() { 
    2359     var img = AJS.IMG({'src': this.img_dir + 'change_lang.gif', 'alt': "Change language"}); 
    2360     img.googie_action_btn = "1"; 
    2361     var switch_lan = AJS.SPAN({'class': 'googie_lang_3d_on', 'style': 'padding-left: 6px;'}, img); 
    2362  
    2363     var fn = function(e) { 
    2364         var elm = AJS.getEventElm(e); 
    2365         if(AJS.nodeName(elm) == 'img') 
    2366             elm = elm.parentNode; 
    2367         if(elm.className == "googie_lang_3d_click") { 
    2368             elm.className = "googie_lang_3d_on"; 
    2369             this.hideLangWindow(); 
    2370         } 
    2371         else { 
    2372             elm.className = "googie_lang_3d_click"; 
    2373             this.showLangWindow(switch_lan); 
    2374         } 
    2375     } 
    2376  
    2377     AJS.AEV(switch_lan, "click", AJS.$b(fn, this)); 
     802} 
     803 
     804this.createChangeLangPic = function() { 
     805    var img = $('<img>') 
     806        .attr({src: this.img_dir + 'change_lang.gif', 'alt': 'Change language', 'googie_action_btn': '1'}); 
     807 
     808    var switch_lan = document.createElement('SPAN'); 
     809    var ref = this; 
     810 
     811    $(switch_lan).addClass('googie_lang_3d_on') 
     812        .append(img) 
     813        .bind('click', function(e) { 
     814            var elm = this.tagName == 'IMG' ? this.parentNode : this; 
     815            if($(elm).hasClass('googie_lang_3d_click')) { 
     816                elm.className = 'googie_lang_3d_on'; 
     817                ref.hideLangWindow(); 
     818            } 
     819            else { 
     820                elm.className = 'googie_lang_3d_click'; 
     821                ref.showLangWindow(elm); 
     822            } 
     823        }); 
     824 
    2378825    return switch_lan; 
    2379826} 
    2380827 
    2381 GoogieSpell.prototype.createSpellDiv = function() { 
    2382     var chk_spell = AJS.SPAN({'class': 'googie_check_spelling_link'}); 
    2383  
    2384     chk_spell.innerHTML = this.lang_chck_spell; 
    2385     var spell_img = null; 
    2386     if(this.show_spell_img) 
    2387         spell_img = AJS.IMG({'src': this.img_dir + "spellc.gif"}); 
    2388     return AJS.SPAN(spell_img, " ", chk_spell); 
     828this.createSpellDiv = function() { 
     829    var span = document.createElement('SPAN'); 
     830 
     831    $(span).addClass('googie_check_spelling_link').text(this.lang_chck_spell); 
     832 
     833    if (this.show_spell_img) { 
     834        $(span).append(' ').append($('<img>').attr('src', this.img_dir + 'spellc.gif')); 
     835    } 
     836    return span; 
    2389837} 
    2390838 
     
    2393841// State functions 
    2394842///// 
    2395 GoogieSpell.prototype.flashNoSpellingErrorState = function(on_finish) { 
    2396     var no_spell_errors; 
    2397  
    2398     if(on_finish) { 
    2399         var fn = function() { 
    2400             on_finish(); 
    2401             this.checkSpellingState(); 
    2402         }; 
    2403         no_spell_errors = fn; 
    2404     } 
    2405     else 
    2406         no_spell_errors = this.checkSpellingState; 
    2407  
    2408     this.setStateChanged("no_error_found"); 
    2409  
    2410     if(this.main_controller) { 
    2411         AJS.hideElement(this.switch_lan_pic); 
    2412  
    2413         var dummy = AJS.IMG({'src': this.img_dir + "blank.gif", 'style': 'height: 16px; width: 1px;'}); 
    2414         var rsm = AJS.SPAN(); 
    2415         rsm.innerHTML = this.lang_no_error_found; 
    2416  
    2417         AJS.RCN(this.spell_span, AJS.SPAN(dummy, rsm)); 
    2418  
    2419         this.spell_span.className = "googie_check_spelling_ok"; 
    2420         this.spell_span.style.textDecoration = "none"; 
    2421         this.spell_span.style.cursor = "default"; 
    2422  
    2423         AJS.callLater(AJS.$b(no_spell_errors, this), 1200, [false]); 
    2424     } 
    2425 } 
    2426  
    2427 GoogieSpell.prototype.resumeEditingState = function() { 
    2428     this.setStateChanged("resume_editing"); 
     843this.flashNoSpellingErrorState = function(on_finish) { 
     844    this.setStateChanged('no_error_found'); 
     845 
     846    var ref = this; 
     847    if (this.main_controller) { 
     848        var no_spell_errors; 
     849        if (on_finish) { 
     850            var fn = function() { 
     851                on_finish(); 
     852                ref.checkSpellingState(); 
     853            }; 
     854            no_spell_errors = fn; 
     855        } 
     856        else 
     857            no_spell_errors = function () { ref.checkSpellingState() }; 
     858 
     859        var rsm = $('<span>').text(this.lang_no_error_found); 
     860         
     861        $(this.switch_lan_pic).hide(); 
     862        $(this.spell_span).empty().append(rsm) 
     863            .removeClass().addClass('googie_check_spelling_ok'); 
     864 
     865        window.setTimeout(no_spell_errors, 1000); 
     866    } 
     867} 
     868 
     869this.resumeEditingState = function() { 
     870    this.setStateChanged('resume_editing'); 
    2429871 
    2430872    //Change link text to resume 
    2431     if(this.main_controller) { 
    2432         AJS.hideElement(this.switch_lan_pic); 
    2433         var dummy = AJS.IMG({'src': this.img_dir + "blank.gif", 'style': 'height: 16px; width: 1px;'}); 
    2434         var rsm = AJS.SPAN(); 
    2435         rsm.innerHTML = this.lang_rsm_edt; 
    2436         AJS.RCN(this.spell_span, AJS.SPAN(dummy, rsm)); 
    2437      
    2438         var fn = function(e) { 
    2439             this.resumeEditing(); 
    2440         } 
    2441         this.spell_span.onclick = AJS.$b(fn, this); 
    2442  
    2443         this.spell_span.className = "googie_resume_editing"; 
     873    if (this.main_controller) { 
     874        var rsm = $('<span>').text(this.lang_rsm_edt); 
     875        var ref = this; 
     876 
     877        $(this.switch_lan_pic).hide(); 
     878        $(this.spell_span).empty().unbind().append(rsm) 
     879            .bind('click', function() { ref.resumeEditing() }) 
     880            .removeClass().addClass('googie_resume_editing'); 
    2444881    } 
    2445882 
    2446883    try { this.edit_layer.scrollTop = this.ta_scroll_top; } 
    2447     catch(e) { } 
    2448 } 
    2449  
    2450 GoogieSpell.prototype.checkSpellingState = function(fire) { 
    2451     if(!AJS.isDefined(fire) || fire) 
    2452         this.setStateChanged("spell_check"); 
    2453  
    2454     if(this.show_change_lang_pic) 
     884    catch (e) {}; 
     885} 
     886 
     887this.checkSpellingState = function(fire) { 
     888    if (fire) 
     889        this.setStateChanged('ready'); 
     890 
     891    if (this.show_change_lang_pic) 
    2455892        this.switch_lan_pic = this.createChangeLangPic(); 
    2456893    else 
    2457         this.switch_lan_pic = AJS.SPAN(); 
     894        this.switch_lan_pic = document.createElement('SPAN'); 
    2458895 
    2459896    var span_chck = this.createSpellDiv(); 
    2460     var fn = function() { 
    2461         this.spellCheck(); 
    2462     }; 
    2463  
    2464     if(this.custom_spellcheck_starter) 
    2465         span_chck.onclick = this.custom_spellcheck_starter; 
     897    var ref = this; 
     898 
     899    if (this.custom_spellcheck_starter) 
     900        $(span_chck).bind('click', function(e) { ref.custom_spellcheck_starter() }); 
    2466901    else { 
    2467         span_chck.onclick = AJS.$b(fn, this); 
     902        $(span_chck).bind('click', function(e) { ref.spellCheck() }); 
     903    } 
     904 
     905    if (this.main_controller) { 
     906        if (this.change_lang_pic_placement == 'left') { 
     907            $(this.spell_container).empty().append(this.switch_lan_pic).append(' ').append(span_chck); 
     908        } else { 
     909            $(this.spell_container).empty().append(span_chck).append(' ').append(this.switch_lan_pic); 
     910        } 
    2468911    } 
    2469912 
    2470913    this.spell_span = span_chck; 
    2471     if(this.main_controller) { 
    2472         if(this.change_lang_pic_placement == "left") 
    2473             AJS.RCN(this.spell_container, span_chck, " ", this.switch_lan_pic); 
    2474         else 
    2475             AJS.RCN(this.spell_container, this.switch_lan_pic, " ", span_chck); 
    2476     } 
    2477     // modified by roundcube 
    2478     this.check_link = span_chck; 
    2479914} 
    2480915 
     
    2483918// Misc. functions 
    2484919///// 
    2485 GoogieSpell.item_onmouseover = function(e) { 
    2486     var elm = AJS.getEventElm(e); 
    2487     if(elm.className != "googie_list_revert" && elm.className != "googie_list_close") 
    2488         elm.className = "googie_list_onhover"; 
    2489     else 
    2490         elm.parentNode.className = "googie_list_onhover"; 
    2491 } 
    2492 GoogieSpell.item_onmouseout = function(e) { 
    2493     var elm = AJS.getEventElm(e); 
    2494     if(elm.className != "googie_list_revert" && elm.className != "googie_list_close") 
    2495         elm.className = "googie_list_onout"; 
    2496     else 
    2497         elm.parentNode.className = "googie_list_onout"; 
    2498 } 
    2499  
    2500 GoogieSpell.prototype.createCloseButton = function(c_fn) { 
    2501     return this.createButton(this.lang_close, 'googie_list_close', AJS.$b(c_fn, this)); 
    2502 } 
    2503  
    2504 GoogieSpell.prototype.createButton = function(name, css_class, c_fn) { 
    2505     var btn_row = AJS.TR(); 
    2506     var btn = AJS.TD(); 
    2507  
    2508     btn.onmouseover = GoogieSpell.item_onmouseover; 
    2509     btn.onmouseout = GoogieSpell.item_onmouseout; 
    2510  
     920this.isDefined = function(o) { 
     921    return (o != 'undefined' && o != null) 
     922} 
     923 
     924this.errorFixed = function() {  
     925    this.cnt_errors_fixed++;  
     926    if (this.all_errors_fixed_observer) 
     927        if (this.cnt_errors_fixed == this.cnt_errors) { 
     928            this.hideErrorWindow(); 
     929            this.all_errors_fixed_observer(); 
     930        } 
     931} 
     932 
     933this.errorFound = function() { 
     934    this.cnt_errors++; 
     935} 
     936 
     937this.createCloseButton = function(c_fn) { 
     938    return this.createButton(this.lang_close, 'googie_list_close', c_fn); 
     939} 
     940 
     941this.createButton = function(name, css_class, c_fn) { 
     942    var btn_row = document.createElement('TR'); 
     943    var btn = document.createElement('TD'); 
    2511944    var spn_btn; 
    2512     if(css_class != "") { 
    2513         spn_btn = AJS.SPAN({'class': css_class}); 
    2514         spn_btn.innerHTML = name; 
    2515     } 
    2516     else { 
    2517         spn_btn = AJS.TN(name); 
    2518     } 
     945 
     946    if (css_class) { 
     947        spn_btn = document.createElement('SPAN'); 
     948        $(spn_btn).addClass(css_class).html(name); 
     949    } else { 
     950        spn_btn = document.createTextNode(name); 
     951    } 
     952 
     953    $(btn).bind('click', c_fn) 
     954        .bind('mouseover', this.item_onmouseover) 
     955        .bind('mouseout', this.item_onmouseout); 
     956 
    2519957    btn.appendChild(spn_btn); 
    2520     AJS.AEV(btn, "click", c_fn); 
    2521958    btn_row.appendChild(btn); 
    2522959 
     
    2524961} 
    2525962 
    2526 GoogieSpell.prototype.removeIndicator = function(elm) { 
     963this.removeIndicator = function(elm) { 
     964    //$(this.indicator).remove(); 
     965    // roundcube mod. 
     966    if (window.rcmail) 
     967        rcmail.set_busy(false); 
     968} 
     969 
     970this.appendIndicator = function(elm) { 
    2527971    // modified by roundcube 
    2528972    if (window.rcmail) 
    2529         rcmail.set_busy(false); 
    2530     //try { AJS.removeElement(this.indicator); } 
    2531     //catch(e) {} 
    2532 } 
    2533  
    2534 GoogieSpell.prototype.appendIndicator = function(elm) { 
    2535     // modified by roundcube 
    2536     if (window.rcmail) 
    2537         rcmail.set_busy(true, 'checking'); 
    2538   /* 
    2539     var img = AJS.IMG({'src': this.img_dir + 'indicator.gif', 'style': 'margin-right: 5px;'}); 
    2540     AJS.setWidth(img, 16); 
    2541     AJS.setHeight(img, 16); 
    2542     this.indicator = img; 
    2543     img.style.textDecoration = "none"; 
    2544     try { 
    2545         AJS.insertBefore(img, elm); 
    2546     } 
    2547     catch(e) {} 
    2548   */ 
    2549 } 
    2550  
    2551 GoogieSpell.prototype.createFocusLink = function(name) { 
    2552     return AJS.A({'href': 'javascript:;', name: name}); 
    2553 } 
     973        rcmail.set_busy(true, 'checking'); 
     974/*     
     975    this.indicator = document.createElement('IMG'); 
     976    $(this.indicator).attr('src', this.img_dir + 'indicator.gif') 
     977        .css({'margin-right': '5px', 'text-decoration': 'none'}).width(16).height(16); 
     978     
     979    if (elm) 
     980        $(this.indicator).insertBefore(elm); 
     981    else 
     982        $('body').append(this.indicator); 
     983*/                                   
     984} 
     985 
     986this.createFocusLink = function(name) { 
     987    var link = document.createElement('A'); 
     988    $(link).attr({'href': 'javascript:;', 'name': name}); 
     989    return link; 
     990} 
     991 
     992this.item_onmouseover = function(e) { 
     993    if (this.className != "googie_list_revert" && this.className != "googie_list_close") 
     994        this.className = "googie_list_onhover"; 
     995    else 
     996        this.parentNode.className = "googie_list_onhover"; 
     997} 
     998this.item_onmouseout = function(e) { 
     999    if (this.className != "googie_list_revert" && this.className != "googie_list_close") 
     1000        this.className = "googie_list_onout"; 
     1001    else 
     1002        this.parentNode.className = "googie_list_onout"; 
     1003} 
     1004 
     1005 
     1006}; 
  • program/steps/mail/compose.inc

    r1fb5874 r309d2f4  
    434434      "googie.setLanguages(%s);\n". 
    435435      "googie.setCurrentLanguage('%s');\n". 
     436      "googie.setSpellContainer('spellcheck-control');\n". 
    436437      "googie.decorateTextarea('%s');\n". 
    437438      "%s.set_env('spellcheck', googie);", 
     
    835836  global $CONFIG, $MESSAGE, $compose_mode; 
    836837 
    837   $choices = array( 
    838     'html'  => 'htmltoggle', 
    839     'plain' => 'plaintoggle' 
    840   ); 
    841  
    842838  // determine whether HTML or plain text should be checked 
    843839  $useHtml = $CONFIG['htmleditor'] ? true : false; 
     
    846842    $useHtml = ($useHtml && $MESSAGE->has_html_part()); 
    847843 
    848   $editorid = empty($attrib['editorid']) ? 'rcmComposeMessage' : $attrib['editorid']; 
    849  
    850   $selector = ''; 
    851   $chosenvalue = $useHtml ? 'html' : 'plain'; 
    852   $radio = new html_radiobutton(array('name' => '_editorSelect', 
    853     'onclick' => "return rcmail_toggle_editor(this.value=='html', '$editorid', '_is_html')")); 
     844  if (empty($attrib['editorid'])) 
     845    $attrib['editorid'] = 'rcmComposeMessage'; 
     846 
     847  if (empty($attrib['name'])) 
     848    $attrib['name'] = 'editorSelect'; 
     849     
     850    $attrib['onchange'] = "return rcmail_toggle_editor(this.value=='html', '".$attrib['editorid']."', '_is_html')"; 
     851 
     852  $select = new html_select($attrib); 
     853 
     854  $select->add(Q(rcube_label('htmltoggle')), 'html'); 
     855  $select->add(Q(rcube_label('plaintoggle')), 'plain'); 
     856 
     857  return $select->show($useHtml ? 'html' : 'plain'); 
    854858 
    855859  foreach ($choices as $value => $text) 
  • skins/default/common.css

    rf055b12 r309d2f4  
    287287} 
    288288 
    289 .radios-left label 
    290 { 
    291   padding-left: 0.3em; 
    292 } 
    293  
    294289/***** common table settings ******/ 
    295290 
  • skins/default/googiespell.css

    rffa6c10 r309d2f4  
    1111  position: absolute; 
    1212  visibility: hidden; 
     13} 
     14 
     15.googie_edit_layer { 
     16  border: 1px solid #666666; 
     17  background-color: #ffffff; 
     18  padding: 1px 4px; 
     19  margin: 1px 0px; 
     20  font-size: 9pt; 
     21  font-family: "Courier New", Courier, monospace; 
     22} 
     23 
     24.googie_edit_layer span { 
     25  font-size: 9pt; 
     26  font-family: "Courier New", Courier, monospace; 
    1327} 
    1428 
     
    6377} 
    6478 
    65 .googie_resume_editing, 
    66 .googie_check_spelling_link { 
     79.googie_check_spelling_link {   
    6780  color: #CC0000; 
    6881  font-size: 11px; 
     
    7184} 
    7285 
    73 .googie_resume_editing:hover, 
    7486.googie_check_spelling_link:hover { 
    7587  text-decoration: underline; 
    76 } 
    77  
    78 .googie_resume_editing { 
    79   color: green; 
    8088} 
    8189 
     
    8492} 
    8593 
    86 .googie_check_spelling_ok { 
     94.googie_check_spelling_ok,  
     95.googie_resume_editing { 
    8796  color: green; 
    8897  font-size: 11px; 
     98  cursor: pointer; 
     99} 
     100 
     101.googie_check_spelling_ok:hover, 
     102.googie_resume_editing:hover { 
    89103  text-decoration: underline; 
    90   cursor: pointer; 
    91104} 
    92105 
  • skins/default/mail.css

    r1fb5874 r309d2f4  
    2020} 
    2121 
    22 #messagetoolbar select 
     22#messagetoolbar select, 
     23#compose-container select 
    2324{ 
    2425  font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; 
    2526  font-size: 11px; 
    2627  color: #333333; 
     28  height: 21px; 
    2729} 
    2830 
     
    914916{ 
    915917  padding-left: 30px; 
     918  white-space: nowrap; 
    916919} 
    917920 
     
    929932} 
    930933 
     934#spellcheck-control 
     935{ 
     936  text-align: right; 
     937  padding-top: 3px; 
     938} 
     939 
     940#editor-select 
     941{ 
     942  float: left; 
     943} 
     944 
    931945#compose-div 
    932946{ 
    933947  position: absolute; 
    934   top: 110px; 
    935   bottom: 40px; 
     948  top: 130px; 
     949  bottom: 30px; 
    936950  width: 100%; 
    937951  vertical-align: top; 
     952  padding-top: 2px; 
    938953} 
    939954 
  • skins/default/templates/compose.html

    r1a76227 r309d2f4  
    6767                <td class="title"><label for="compose-subject"><roundcube:label name="subject" /></label></td> 
    6868                <td><roundcube:object name="composeSubject" id="compose-subject" form="form" tabindex="6" /></td> 
     69            </tr><tr> 
     70                <td class="title"><roundcube:label name="editortype" /></td> 
     71                <td> 
     72                    <div id="editor-select"><roundcube:object name="editorSelector" editorid="compose-body" tabindex="7" /></div> 
     73                    <div id="spellcheck-control"></div> 
     74                </td> 
    6975            </tr> 
    7076        </tbody> 
     
    7278    </div> 
    7379    <div id="compose-div"> 
    74         <roundcube:object name="composeBody" id="compose-body" form="form" cols="70" rows="20" tabindex="7" /> 
     80        <roundcube:object name="composeBody" id="compose-body" form="form" cols="70" rows="20" tabindex="8" /> 
    7581        <table border="0" cellspacing="0" summary="" style="width:100%; margin-top: 5px;"><tbody> 
    7682            <tr> 
     
    7985                    <roundcube:button type="input" command="list" class="button" label="cancel" tabindex="9" /> 
    8086                </td> 
    81                 <td style="text-align:center; white-space: nowrap"> 
    82                     <label><roundcube:label name="savesentmessagein" />: <roundcube:object name="storetarget" maxlength="30" /></label> 
    83                 </td> 
    84                 <td style="text-align:right; white-space:nowrap"> 
    85                     <roundcube:label name="editortype" />:&nbsp; 
    86                     <span class="radios-left"><roundcube:object name="editorSelector" editorid="compose-body" tabindex="10" /></span> 
     87                <td style="text-align:right; white-space: nowrap"> 
     88                    <label><roundcube:label name="savesentmessagein" />: <roundcube:object name="storetarget" maxlength="30" tabindex="10" /></label> 
    8789                </td> 
    8890            </tr> 
Note: See TracChangeset for help on using the changeset viewer.