googiespell.min.js 17.4 KB
/**
 * Roundcube SpellCheck script
 *
 * jQuery'fied spell checker based on GoogieSpell 4.0
 * (which was published under GPL "version 2 or any later version")
 *
 * @licstart  The following is the entire license notice for the
 * JavaScript code in this file.
 *
 * Copyright (C) 2006 Amir Salihefendic
 * Copyright (C) The Roundcube Dev Team
 * Copyright (C) Kolab Systems AG
 *
 * The JavaScript code in this page is free software: you can
 * redistribute it and/or modify it under the terms of the GNU
 * General Public License (GNU GPL) as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version.  The code is distributed WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
 *
 * As additional permission under GNU GPL version 3 section 7, you
 * may distribute non-source (e.g., minimized or compacted) forms of
 * that code without the copy of the GNU GPL normally required by
 * section 4, provided you include this license notice and a URL
 * through which recipients can access the Corresponding Source.
 *
 * @licend  The above is the entire license notice
 * for the JavaScript code in this file.
 *
 * @author 4mir Salihefendic <amix@amix.dk>
 * @author Aleksander Machniak - <alec [at] alec.pl>
 */
var GOOGIE_CUR_LANG,GOOGIE_DEFAULT_LANG="en";function GoogieSpell(t,e,i){var s=this,r=rcmail.get_cookie("language");GOOGIE_CUR_LANG=null!=r?r:GOOGIE_DEFAULT_LANG,this.array_keys=function(t){var e,i=[];for(e in t)i.push([e]);return i},this.img_dir=t,this.server_url=e,this.org_lang_to_word={da:"Dansk",de:"Deutsch",en:"English",es:"Español",fr:"Français",it:"Italiano",nl:"Nederlands",pl:"Polski",pt:"Português",ru:"Русский",fi:"Suomi",sv:"Svenska"},this.lang_to_word=this.org_lang_to_word,this.langlist_codes=this.array_keys(this.lang_to_word),this.show_change_lang_pic=!1,this.change_lang_pic_placement="right",this.report_state_change=!0,this.ta_scroll_top=0,this.el_scroll_top=0,this.lang_chck_spell="Check spelling",this.lang_revert="Revert to",this.lang_close="Close",this.lang_rsm_edt="Resume editing",this.lang_no_error_found="No spelling errors found",this.lang_no_suggestions="No suggestions",this.lang_learn_word="Add to dictionary",this.use_ok_pic=!1,this.show_spell_img=!1,this.decoration=!0,this.use_close_btn=!1,this.edit_layer_dbl_click=!0,this.report_ta_not_found=!0,this.custom_ajax_error=null,this.custom_no_spelling_error=null,this.extra_menu_items=[],this.custom_spellcheck_starter=null,this.main_controller=!0,this.has_dictionary=i,this.lang_state_observer=null,this.spelling_state_observer=null,this.show_menu_observer=null,this.all_errors_fixed_observer=null,this.use_focus=!1,this.focus_link_t=null,this.focus_link_b=null,this.cnt_errors=0,this.cnt_errors_fixed=0,$(document).click(function(t){"1"!=$(t.target).attr("googie_action_btn")&&s.isErrorWindowShown()&&s.hideErrorWindow()}),this.decorateTextarea=function(t){var e,i,s,r,o;this.text_area="string"==typeof t?document.getElementById(t):t,this.text_area?(!this.spell_container&&this.decoration&&(e=document.createElement("table"),i=document.createElement("tbody"),s=document.createElement("tr"),r=document.createElement("td"),o=this.isDefined(this.force_width)?this.force_width:this.text_area.offsetWidth,t=this.isDefined(this.force_height)?this.force_height:16,s.appendChild(r),i.appendChild(s),$(e).append(i).insertBefore(this.text_area).width("100%").height(t),$(r).height(t).width(o).css("text-align","right"),this.spell_container=r),this.checkSpellingState()):this.report_ta_not_found&&rcmail.alert_dialog("Text area not found")},this.setSpellContainer=function(t){this.spell_container="string"==typeof t?document.getElementById(t):t},this.setLanguages=function(t){this.lang_to_word=t,this.langlist_codes=this.array_keys(t)},this.setCurrentLanguage=function(t){GOOGIE_CUR_LANG=t,rcmail.set_cookie("language",t,!1)},this.setForceWidthHeight=function(t,e){this.force_width=t,this.force_height=e},this.setDecoration=function(t){this.decoration=t},this.dontUseCloseButtons=function(){this.use_close_btn=!1},this.appendNewMenuItem=function(t,e,i){this.extra_menu_items.push([t,e,i])},this.setFocus=function(){try{return this.focus_link_b.focus(),this.focus_link_t.focus(),!0}catch(t){return!1}},this.setStateChanged=function(t){this.state=t,null!=this.spelling_state_observer&&this.report_state_change&&this.spelling_state_observer(t,this)},this.setReportStateChange=function(t){this.report_state_change=t},this.getUrl=function(){return this.server_url+GOOGIE_CUR_LANG},this.escapeSpecial=function(t){return t?t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"):""},this.createXMLReq=function(t){return'<?xml version="1.0" encoding="utf-8" ?><spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1"><text>'+t+"</text></spellrequest>"},this.spellCheck=function(t){this.prepare(t);var t=this.escapeSpecial(this.original_text),e=this;$.ajax({type:"POST",url:this.getUrl(),data:this.createXMLReq(t),dataType:"text",error:function(t){e.custom_ajax_error?e.custom_ajax_error(e):rcmail.alert_dialog("An error was encountered on the server. Please try again later."),e.main_controller&&($(e.spell_span).remove(),e.removeIndicator()),e.checkSpellingState()},success:function(t){e.processData(t),e.results.length||(e.custom_no_spelling_error?e.custom_no_spelling_error(e):e.flashNoSpellingErrorState()),e.removeIndicator()}})},this.learnWord=function(t,e){t=this.escapeSpecial(t.innerHTML);var i=this,t='<?xml version="1.0" encoding="utf-8" ?><learnword><text>'+t+"</text></learnword>";$.ajax({type:"POST",url:this.getUrl(),data:t,dataType:"text",error:function(t){i.custom_ajax_error?i.custom_ajax_error(i):rcmail.alert_dialog("An error was encountered on the server. Please try again later.")},success:function(t){}})},this.prepare=function(t,e){this.cnt_errors_fixed=0,this.cnt_errors=0,this.setStateChanged("checking_spell"),this.original_text="",!e&&this.main_controller&&this.appendIndicator(this.spell_span),this.error_links=[],this.ta_scroll_top=this.text_area.scrollTop,this.ignore=t;e=$(this.text_area);if(""==e.val()||t)return this.custom_no_spelling_error?this.custom_no_spelling_error(this):this.flashNoSpellingErrorState(),void this.removeIndicator();t="border-box"==$(e).css("box-sizing")?this.text_area.offsetHeight:$(e).height();this.createEditLayer(e.width(),t),this.createErrorWindow(),$("body").append(this.error_window),this.main_controller&&$(this.spell_span).off("click"),this.original_text=e.val()},this.parseResult=function(t){var e=/\w+="(\d+|true)"/g,i=/\t/g,s=t.match(/<c[^>]*>[^<]*<\/c>/g),r=[];if(null==s)return r;for(var o=0,n=s.length;o<n;o++){var a=[];this.errorFound(),a.attrs=[];for(var l,h,c=s[o].match(e),_=0;_<c.length;_++)h=(l=c[_].split(/=/))[1].replace(/"/g,""),a.attrs[l[0]]="true"!=h?parseInt(h):h;a.suggestions=[];for(var u=s[o].replace(/<[^>]*>/g,"").split(i),d=0;d<u.length;d++)""!=u[d]&&a.suggestions.push(u[d]);r.push(a)}return r},this.processData=function(t){this.results=this.parseResult(t),this.results.length&&(this.showErrorsInIframe(),this.resumeEditingState())},this.createErrorWindow=function(){this.error_window=document.createElement("div"),$(this.error_window).addClass("googie_window popupmenu").attr("googie_action_btn","1")},this.isErrorWindowShown=function(){return $(this.error_window).is(":visible")},this.hideErrorWindow=function(){$(this.error_window).hide(),$(this.error_window_iframe).hide()},this.updateOriginalText=function(t,e,i,s){var r=this.original_text.substring(0,t),t=this.original_text.substring(t+e.length),o=i.length-e.length;this.original_text=r+i+t,$(this.text_area).val(this.original_text);for(var n=0,a=this.results.length;n<a;n++)n!=s&&s<n&&(this.results[n].attrs.o+=o)},this.saveOldValue=function(t,e){t.is_changed=!0,t.old_value=e},this.createListSeparator=function(){return $("<li>").html("&nbsp;").attr("googie_action_btn","1").css({cursor:"default","font-size":"3px","border-top":"1px solid #ccc","padding-top":"3px"}).get(0)},this.correctError=function(t,e,i,s){var r=e.innerHTML,o=3==i.nodeType?i.nodeValue:i.innerHTML,i=this.results[t].attrs.o;s&&(s=e.previousSibling.innerHTML,e.previousSibling.innerHTML=s.slice(0,s.length-1),r=" "+r,i--),this.hideErrorWindow(),this.updateOriginalText(i,r,o,t),$(e).html(o).css("color","green").attr("is_corrected",!0),this.results[t].attrs.l=o.length,this.isDefined(e.old_value)||this.saveOldValue(e,r),this.errorFixed()},this.ignoreError=function(t,e){$(t).removeAttr("class").css("color","").off(),this.hideErrorWindow()},this.showErrorWindow=function(r,e){this.show_menu_observer&&this.show_menu_observer(this);var o=this,t=$(r).offset(),n=document.createElement("ul");$(this.error_window).html(""),$(n).addClass("googie_list toolbarmenu").attr("googie_action_btn","1");var i=this.results[e].suggestions,s=this.results[e].attrs.o;this.results[e].attrs.l;this.has_dictionary&&!$(r).attr("is_corrected")&&(l=$("<a>").text(this.lang_learn_word).addClass("googie_add_to_dict active"),$("<li>").attr("googie_action_btn","1").css("cursor","default").mouseover(o.item_onmouseover).mouseout(o.item_onmouseout).click(function(t){o.learnWord(r,e),o.ignoreError(r,e)}).append(l).appendTo(n));for(var a,l,h=0,c=i.length;h<c;h++)l=$("<a>").html(i[h]).addClass("active"),$("<li>").mouseover(this.item_onmouseover).mouseout(this.item_onmouseout).click(function(t){o.correctError(e,r,t.target.firstChild)}).append(l).appendTo(n);r.is_changed&&r.innerHTML!=r.old_value&&(a=r.old_value,l=$("<a>").addClass("googie_list_revert active").html(this.lang_revert+" "+a),$("<li>").mouseover(this.item_onmouseover).mouseout(this.item_onmouseout).click(function(t){o.updateOriginalText(s,r.innerHTML,a,e),$(r).removeAttr("is_corrected").css("color","#b91414").html(a),o.hideErrorWindow()}).append(l).appendTo(n));var _=document.createElement("li"),u=document.createElement("input"),d=document.createElement("button"),g=document.createElement("form"),p=function(){return""!=u.value&&(o.isDefined(r.old_value)||o.saveOldValue(r,r.innerHTML),o.updateOriginalText(s,r.innerHTML,u.value,e),$(r).attr("is_corrected",!0).css("color","green").text(u.value),o.hideErrorWindow()),!1};$(u).width(120).val($(r).text()).attr("googie_action_btn","1"),$(_).css("cursor","default").attr("googie_action_btn","1").on("click",function(){return!1}),this.use_ok_pic?$("<img>").attr("src",this.img_dir+"ok.gif").width(32).height(16).css({cursor:"pointer","margin-left":"2px","margin-right":"2px"}).appendTo(d):$(d).text("OK"),$(d).addClass("mainaction save googie_ok_button btn-sm").click(p),$(g).attr("googie_action_btn","1").css({cursor:"default","white-space":"nowrap"}).submit(p).append(u).append(d).appendTo(_),n.appendChild(_),0<this.extra_menu_items.length&&n.appendChild(this.createListSeparator());var m=function(t){var e,i,s;t<o.extra_menu_items.length&&((e=o.extra_menu_items[t])[2]&&!e[2](r,o)||(i=document.createElement("tr"),s=document.createElement("td"),$(s).html(e[0]).mouseover(o.item_onmouseover).mouseout(o.item_onmouseout).click(function(){return e[1](r,o)}),i.appendChild(s),n.appendChild(i)),m(t+1))};m(0),m=null,this.use_close_btn&&n.appendChild(this.createCloseButton(this.hideErrorWindow)),this.error_window.appendChild(n),rcmail.triggerEvent("googiespell_create",{obj:this.error_window});g=$(this.error_window).height(),p=$(this.error_window).width(),d=$(document).height(),_=$(document).width(),g=t.top+g+20<d?t.top+20:t.top-g,p=t.left+p<_?t.left:t.left-p;p<0&&(p=0),g<0&&(g=0),$(this.error_window).css({top:g+"px",left:p+"px",position:"absolute"}).show(),document.all&&!window.opera&&(this.error_window_iframe||(p=$("<iframe>").css({position:"absolute","z-index":-1}),$("body").append(p),this.error_window_iframe=p),$(this.error_window_iframe).css({top:this.error_window.offsetTop,left:this.error_window.offsetLeft,width:this.error_window.offsetWidth,height:this.error_window.offsetHeight}).show())},this.createEditLayer=function(t,e){this.edit_layer=document.createElement("div"),$(this.edit_layer).addClass("googie_edit_layer").attr("id","googie_edit_layer").width(t).height(e),"input"!=this.text_area.nodeName.toLowerCase()||""==$(this.text_area).val()?$(this.edit_layer).css("overflow","auto"):$(this.edit_layer).css("overflow","hidden");var i=this;this.edit_layer_dbl_click&&$(this.edit_layer).dblclick(function(t){var e;return"googie_link"==t.target.className||i.isErrorWindowShown()||(i.resumeEditing(),e=function(){$(i.text_area).focus(),e=null},setTimeout(e,10)),!1})},this.resumeEditing=function(){this.setStateChanged("ready"),this.edit_layer&&(this.el_scroll_top=this.edit_layer.scrollTop),this.hideErrorWindow(),this.main_controller&&$(this.spell_span).removeClass().addClass("googie_no_style"),this.ignore||(this.use_focus&&($(this.focus_link_t).remove(),$(this.focus_link_b).remove()),$(this.edit_layer).remove(),$(this.text_area).show(),null!=this.el_scroll_top&&(this.text_area.scrollTop=this.el_scroll_top)),this.checkSpellingState(!1)},this.createErrorLink=function(t,e){var i=document.createElement("span"),s=this,r=function(t){return s.showErrorWindow(i,e),r=null,!1};return $(i).html(t).addClass("googie_link").click(r).removeAttr("is_corrected").attr({googie_action_btn:"1",g_id:e}),i},this.createPart=function(t){if(" "==t)return document.createTextNode(" ");t=(t=(t=(t=(t=this.escapeSpecial(t)).replace(/\n/g,"<br>")).replace(/    /g," &nbsp;")).replace(/^ /g,"&nbsp;")).replace(/ $/g,"&nbsp;");var e=document.createElement("span");return $(e).html(t),e},this.showErrorsInIframe=function(){var t=document.createElement("div"),e=0,i=this.results;if(0<i.length){for(var s=0,r=i.length;s<r;s++){var o=i[s].attrs.o,n=i[s].attrs.l,a=this.original_text.substring(e,o),a=this.createPart(a);t.appendChild(a),e+=o-e;o=this.createErrorLink(this.original_text.substr(o,n),s);this.error_links.push(o),t.appendChild(o),e+=n}var l=this.original_text.substr(e,this.original_text.length),l=this.createPart(l);t.appendChild(l)}else t.innerHTML=this.original_text;$(t).css("text-align","left");var h=this;this.custom_item_evaluator&&$.map(this.error_links,function(t){h.custom_item_evaluator(h,t)}),$(this.edit_layer).append(t),$(this.text_area).hide(),$(this.edit_layer).insertBefore(this.text_area),this.use_focus&&(this.focus_link_t=this.createFocusLink("focus_t"),this.focus_link_b=this.createFocusLink("focus_b"),$(this.focus_link_t).insertBefore(this.edit_layer),$(this.focus_link_b).insertAfter(this.edit_layer))},this.deHighlightCurSel=function(){$(this.lang_cur_elm).removeClass().addClass("googie_list_onout")},this.highlightCurSel=function(){null==GOOGIE_CUR_LANG&&(GOOGIE_CUR_LANG=GOOGIE_DEFAULT_LANG);for(var t=0;t<this.lang_elms.length;t++)$(this.lang_elms[t]).attr("googieId")==GOOGIE_CUR_LANG?(this.lang_elms[t].className="googie_list_selected",this.lang_cur_elm=this.lang_elms[t]):this.lang_elms[t].className="googie_list_onout"},this.createSpellDiv=function(){var t=document.createElement("span");return $(t).addClass("googie_check_spelling_link").text(this.lang_chck_spell),this.show_spell_img&&$(t).append(" ").append($("<img>").attr("src",this.img_dir+"spellc.gif")),t},this.flashNoSpellingErrorState=function(t){this.setStateChanged("no_error_found");var e,i,s=this;this.main_controller&&(e=t?function(){t(),s.checkSpellingState()}:function(){s.checkSpellingState()},i=$("<span>").text(this.lang_no_error_found),$(this.switch_lan_pic).hide(),$(this.spell_span).empty().append(i).removeClass().addClass("googie_check_spelling_ok"),setTimeout(e,1e3))},this.resumeEditingState=function(){var t,e;this.setStateChanged("resume_editing"),this.main_controller&&(t=$("<span>").text(this.lang_rsm_edt),e=this,$(this.switch_lan_pic).hide(),$(this.spell_span).empty().off().append(t).click(function(){e.resumeEditing()}).removeClass().addClass("googie_resume_editing"));try{this.edit_layer.scrollTop=this.ta_scroll_top}catch(t){}},this.checkSpellingState=function(t){t&&this.setStateChanged("ready"),this.switch_lan_pic=document.createElement("span");var t=this.createSpellDiv(),e=this;this.custom_spellcheck_starter?$(t).click(function(t){e.custom_spellcheck_starter()}):$(t).click(function(t){e.spellCheck()}),this.main_controller&&("left"==this.change_lang_pic_placement?$(this.spell_container).empty().append(this.switch_lan_pic).append(" ").append(t):$(this.spell_container).empty().append(t).append(" ").append(this.switch_lan_pic)),this.spell_span=t},this.isDefined=function(t){return null!=t},this.errorFixed=function(){this.cnt_errors_fixed++,this.all_errors_fixed_observer&&this.cnt_errors_fixed==this.cnt_errors&&(this.hideErrorWindow(),this.all_errors_fixed_observer())},this.errorFound=function(){this.cnt_errors++},this.createCloseButton=function(t){return this.createButton(this.lang_close,"googie_list_close",t)},this.createButton=function(t,e,i){var s,r=document.createElement("tr"),o=document.createElement("td");return e?(s=document.createElement("span"),$(s).addClass(e).html(t)):s=document.createTextNode(t),$(o).click(i).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout),o.appendChild(s),r.appendChild(o),r},this.removeIndicator=function(t){window.rcmail&&rcmail.set_busy(!1,null,this.rc_msg_id)},this.appendIndicator=function(t){window.rcmail&&(this.rc_msg_id=rcmail.set_busy(!0,"checking"))},this.createFocusLink=function(t){var e=document.createElement("a");return $(e).attr({href:"javascript:;",name:t}),e},this.item_onmouseover=function(t){"googie_list_revert"!=this.className&&"googie_list_close"!=this.className?this.className="googie_list_onhover":this.parentNode.className="googie_list_onhover"},this.item_onmouseout=function(t){"googie_list_revert"!=this.className&&"googie_list_close"!=this.className?this.className="googie_list_onout":this.parentNode.className="googie_list_onout"}}