- Unified (single) spellchecker button
| | |
| | | CHANGELOG Roundcube Webmail |
| | | =========================== |
| | | |
| | | - Unified (single) spellchecker button |
| | | - Fix encoding of attachment with comma in name (#1488389) |
| | | - Scroll long lists on drag&drop (#1485946) |
| | | - Fix handling of % character in IMAP protocol (#1488382) |
| | |
| | | $.merge(this.env.compose_commands, ['add-recipient', 'firstpage', 'previouspage', 'nextpage', 'lastpage']); |
| | | |
| | | if (this.env.spellcheck) { |
| | | this.env.spellcheck.spelling_state_observer = function(s){ ref.set_spellcheck_state(s); }; |
| | | this.env.spellcheck.spelling_state_observer = function(s) { ref.spellcheck_state(); }; |
| | | this.env.compose_commands.push('spellcheck') |
| | | this.set_spellcheck_state('ready'); |
| | | if ($("input[name='_is_html']").val() == '1') |
| | | this.display_spellcheck_controls(false); |
| | | this.enable_command('spellcheck', true); |
| | | } |
| | | |
| | | document.onmouseup = function(e){ return p.doc_mouse_up(e); }; |
| | |
| | | break; |
| | | |
| | | case 'spellcheck': |
| | | if (window.tinyMCE && tinyMCE.get(this.env.composebody)) { |
| | | tinyMCE.execCommand('mceSpellCheck', true); |
| | | if (this.spellcheck_state()) { |
| | | this.stop_spellchecking(); |
| | | } |
| | | else if (this.env.spellcheck && this.env.spellcheck.spellCheck && this.spellcheck_ready) { |
| | | this.env.spellcheck.spellCheck(); |
| | | this.set_spellcheck_state('checking'); |
| | | else { |
| | | if (window.tinyMCE && tinyMCE.get(this.env.composebody)) { |
| | | tinyMCE.execCommand('mceSpellCheck', true); |
| | | } |
| | | else if (this.env.spellcheck && this.env.spellcheck.spellCheck) { |
| | | this.env.spellcheck.spellCheck(); |
| | | } |
| | | } |
| | | this.spellcheck_state(); |
| | | break; |
| | | |
| | | case 'savedraft': |
| | |
| | | |
| | | this.toggle_editor = function(props) |
| | | { |
| | | this.stop_spellchecking(); |
| | | |
| | | if (props.mode == 'html') { |
| | | this.display_spellcheck_controls(false); |
| | | this.plain2html($('#'+props.id).val(), props.id); |
| | | tinyMCE.execCommand('mceAddControl', false, props.id); |
| | | |
| | |
| | | } |
| | | else { |
| | | var thisMCE = tinyMCE.get(props.id), existingHtml; |
| | | if (thisMCE.plugins.spellchecker && thisMCE.plugins.spellchecker.active) |
| | | thisMCE.execCommand('mceSpellCheck', false); |
| | | |
| | | if (existingHtml = thisMCE.getContent()) { |
| | | if (!confirm(this.get_label('editorwarning'))) { |
| | |
| | | this.html2plain(existingHtml, props.id); |
| | | } |
| | | tinyMCE.execCommand('mceRemoveControl', false, props.id); |
| | | this.display_spellcheck_controls(true); |
| | | } |
| | | |
| | | return true; |
| | |
| | | this.stop_spellchecking = function() |
| | | { |
| | | var ed; |
| | | |
| | | if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody))) { |
| | | if (ed.plugins.spellchecker && ed.plugins.spellchecker.active) |
| | | ed.execCommand('mceSpellCheck'); |
| | | } |
| | | else if ((ed = this.env.spellcheck) && !this.spellcheck_ready) { |
| | | $(ed.spell_span).trigger('click'); |
| | | this.set_spellcheck_state('ready'); |
| | | else if (ed = this.env.spellcheck) { |
| | | if (ed.state && ed.state != 'ready' && ed.state != 'no_error_found') |
| | | $(ed.spell_span).trigger('click'); |
| | | } |
| | | |
| | | this.spellcheck_state(); |
| | | }; |
| | | |
| | | this.display_spellcheck_controls = function(vis) |
| | | this.spellcheck_state = function() |
| | | { |
| | | if (this.env.spellcheck) { |
| | | // stop spellchecking process |
| | | if (!vis) |
| | | this.stop_spellchecking(); |
| | | var ed, active; |
| | | |
| | | $(this.env.spellcheck.spell_container)[vis ? 'show' : 'hide'](); |
| | | } |
| | | }; |
| | | if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody)) && ed.plugins.spellchecker) |
| | | active = ed.plugins.spellchecker.active; |
| | | else if ((ed = this.env.spellcheck) && ed.state) |
| | | active = ed.state != 'ready' && ed.state != 'no_error_found'; |
| | | |
| | | this.set_spellcheck_state = function(s) |
| | | { |
| | | this.spellcheck_ready = (s == 'ready' || s == 'no_error_found'); |
| | | this.enable_command('spellcheck', this.spellcheck_ready); |
| | | $('#'+rcmail.buttons.spellcheck[0].id)[active ? 'addClass' : 'removeClass']('selected'); |
| | | |
| | | return active; |
| | | }; |
| | | |
| | | // get selected language |
| | | this.spellcheck_lang = function() |
| | | { |
| | | var ed; |
| | | if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody)) && ed.plugins.spellchecker) { |
| | | |
| | | if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody)) && ed.plugins.spellchecker) |
| | | return ed.plugins.spellchecker.selectedLang; |
| | | } |
| | | else if (this.env.spellcheck) { |
| | | else if (this.env.spellcheck) |
| | | return GOOGIE_CUR_LANG; |
| | | } |
| | | }; |
| | | |
| | | this.spellcheck_lang_set = function(lang) |
| | | { |
| | | var editor; |
| | | |
| | | if (window.tinyMCE && (editor = tinyMCE.get(this.env.composebody))) |
| | | editor.plugins.spellchecker.selectedLang = lang; |
| | | else if (this.env.spellcheck) |
| | | this.env.spellcheck.setCurrentLanguage(lang); |
| | | }; |
| | | |
| | | // resume spellchecking, highlight provided mispellings without new ajax request |
| | |
| | | sp.prepare(false, true); |
| | | sp.processData(data); |
| | | } |
| | | |
| | | this.spellcheck_state(); |
| | | } |
| | | |
| | | this.set_draft_id = function(id) |
| | |
| | | theme_advanced_buttons1: 'bold,italic,underline,strikethrough,justifyleft,justifycenter,justifyright,justifyfull,separator,outdent,indent,charmap,hr,link,unlink,code,forecolor', |
| | | theme_advanced_buttons2: ',fontselect,fontsizeselect' |
| | | }); |
| | | else // mail compose |
| | | else { // mail compose |
| | | $.extend(conf, { |
| | | plugins: 'paste,emotions,media,nonbreaking,table,searchreplace,visualchars,directionality,tabfocus' + (config.spellcheck ? ',spellchecker' : ''), |
| | | theme_advanced_buttons1: 'bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,outdent,indent,ltr,rtl,blockquote,|,forecolor,backcolor,fontselect,fontsizeselect', |
| | | theme_advanced_buttons2: 'link,unlink,table,|,emotions,charmap,image,media,|,code,search' + (config.spellcheck ? ',spellchecker' : '') + ',undo,redo', |
| | | theme_advanced_buttons2: 'link,unlink,table,|,emotions,charmap,image,media,|,code,search,undo,redo', |
| | | spellchecker_languages: (rcmail.env.spellcheck_langs ? rcmail.env.spellcheck_langs : 'Dansk=da,Deutsch=de,+English=en,Espanol=es,Francais=fr,Italiano=it,Nederlands=nl,Polski=pl,Portugues=pt,Suomi=fi,Svenska=sv'), |
| | | spellchecker_rpc_url: '?_task=utils&_action=spell_html', |
| | | spellchecker_enable_learn_rpc: config.spelldict, |
| | |
| | | oninit: 'rcmail_editor_callback' |
| | | }); |
| | | |
| | | // add handler for spellcheck button state update |
| | | conf.setup = function(ed) { |
| | | ed.onSetProgressState.add(function(ed, active) { |
| | | if (!active) |
| | | rcmail.spellcheck_state(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // support external configuration settings e.g. from skin |
| | | if (window.rcmail_editor_settings) |
| | | $.extend(conf, window.rcmail_editor_settings); |
| | |
| | | if (!$spellcheck_langs[$lang]) |
| | | $lang = 'en'; |
| | | |
| | | $OUTPUT->set_env('spell_langs', $spellcheck_langs); |
| | | $OUTPUT->set_env('spell_lang', $lang); |
| | | |
| | | $editor_lang_set = array(); |
| | | foreach ($spellcheck_langs as $key => $name) { |
| | | $editor_lang_set[] = ($key == $lang ? '+' : '') . JQ($name).'='.JQ($key); |
| | |
| | | "googie.lang_learn_word = \"%s\";\n". |
| | | "googie.setLanguages(%s);\n". |
| | | "googie.setCurrentLanguage('%s');\n". |
| | | "googie.setSpellContainer('spellcheck-control');\n". |
| | | "googie.setDecoration(false);\n". |
| | | "googie.decorateTextarea('%s');\n". |
| | | "%s.set_env('spellcheck', googie);", |
| | | $RCMAIL->output->get_skin_path(), |
| | |
| | | padding: 2px 10px; |
| | | text-decoration: none; |
| | | min-height: 14px; |
| | | background: transparent; |
| | | } |
| | | |
| | | .popupmenu li a.active, |
| | |
| | | color: #333; |
| | | } |
| | | |
| | | .popupmenu li a.active:hover |
| | | .popupmenu li a.active:hover, |
| | | .popupmenu.selectable li a.selected:hover |
| | | { |
| | | color: #fff; |
| | | background-color: #c00; |
| | |
| | | float: left; |
| | | } |
| | | |
| | | .popupmenu.selectable li a.selected |
| | | { |
| | | background: url(images/messageicons.png) 2px -372px no-repeat; |
| | | } |
| | | |
| | | .popupmenu.selectable li a |
| | | { |
| | | padding-left: 20px; |
| | | } |
| | | |
| | | .darkbg |
| | | { |
| | | background-color: #F2F2F2 !important; |
| | |
| | | groupmenu: {id:'groupoptionsmenu', above:1}, |
| | | mailboxmenu: {id:'mailboxoptionsmenu', above:1}, |
| | | composemenu: {id:'composeoptionsmenu', editable:1, overlap:1}, |
| | | spellmenu: {id:'spellmenu'}, |
| | | // toggle: #1486823, #1486930 |
| | | uploadmenu: {id:'attachment-form', editable:1, above:1, toggle:!bw.ie&&!bw.linux }, |
| | | uploadform: {id:'upload-form', editable:1, toggle:!bw.ie&&!bw.linux } |
| | |
| | | rcmail.set_list_options(cols, sort, ord, thread == 'thread' ? 1 : 0); |
| | | }, |
| | | |
| | | spellmenu: function(show) |
| | | { |
| | | var link, li, |
| | | lang = rcmail.spellcheck_lang(), |
| | | menu = this.popups.spellmenu.obj, |
| | | ul = $('ul', menu); |
| | | |
| | | if (!ul.length) { |
| | | ul = $('<ul>'); |
| | | |
| | | for (i in rcmail.env.spell_langs) { |
| | | li = $('<li>'); |
| | | link = $('<a href="#">').text(rcmail.env.spell_langs[i]) |
| | | .addClass('active').data('lang', i) |
| | | .click(function() { |
| | | rcmail.spellcheck_lang_set($(this).data('lang')); |
| | | }); |
| | | |
| | | link.appendTo(li); |
| | | li.appendTo(ul); |
| | | } |
| | | |
| | | ul.appendTo(menu); |
| | | } |
| | | |
| | | // select current language |
| | | $('li', ul).each(function() { |
| | | var el = $('a', this); |
| | | if (el.data('lang') == lang) |
| | | el.addClass('selected'); |
| | | else if (el.hasClass('selected')) |
| | | el.removeClass('selected'); |
| | | }); |
| | | |
| | | this.show_popupmenu('spellmenu', show); |
| | | }, |
| | | |
| | | body_mouseup: function(evt, p) |
| | | { |
| | | var i, target = rcube_event.get_target(evt); |
| | |
| | | opacity: 0.35; |
| | | } |
| | | |
| | | #messagetoolbar a.button.selected { |
| | | background-color: #ddd; |
| | | margin-left: 4px; |
| | | margin-right: 4px; |
| | | margin-top: -1px; |
| | | border: 1px solid #ccc; |
| | | border-radius: 3px; |
| | | -moz-border-radius: 3px; |
| | | -webkit-border-radius: 3px; |
| | | } |
| | | |
| | | #messagetoolbar a.checkmailSel { |
| | | background-position: 0 -32px; |
| | | } |
| | |
| | | <head> |
| | | <title><roundcube:object name="productname" /> :: <roundcube:label name="compose" /></title> |
| | | <roundcube:include file="/includes/links.html" /> |
| | | <roundcube:if condition="config:enable_spellcheck" /> |
| | | <link rel="stylesheet" type="text/css" href="/googiespell.css" /> |
| | | <roundcube:endif /> |
| | | <script type="text/javascript" src="/functions.js"></script> |
| | | <script type="text/javascript" src="/splitter.js"></script> |
| | | <style type="text/css"> |
| | |
| | | <div id="messagetoolbar"> |
| | | <roundcube:button command="list" type="link" class="button back" classAct="button back" classSel="button backSel" title="backtolist" content=" " /> |
| | | <roundcube:button command="send" type="link" class="buttonPas send" classAct="button send" classSel="button sendSel" title="sendmessage" content=" " /> |
| | | <roundcube:button command="spellcheck" type="link" class="buttonPas spellcheck" classAct="button spellcheck" classSel="button spellcheckSel" title="checkspelling" content=" " /> |
| | | <roundcube:if condition="config:enable_spellcheck" /> |
| | | <span class="dropbutton"> |
| | | <roundcube:button command="spellcheck" type="link" class="buttonPas spellcheck" classAct="button spellcheck" classSel="button spellcheckSel" title="checkspelling" content=" " /> |
| | | <span id="spellmenulink" onclick="rcmail_ui.show_popup('spellmenu');return false"></span> |
| | | </span> |
| | | <roundcube:endif /> |
| | | <roundcube:button name="addattachment" type="link" class="button attach" classAct="button attach" classSel="button attachSel" title="addattachment" onclick="rcmail_ui.show_popup('uploadmenu', true);return false" content=" " /> |
| | | <roundcube:button command="insert-sig" type="link" class="buttonPas insertsig" classAct="button insertsig" classSel="button insertsigSel" title="insertsignature" content=" " /> |
| | | <roundcube:button command="savedraft" type="link" class="buttonPas savedraft" classAct="button savedraft" classSel="button savedraftSel" title="savemessage" content=" " /> |
| | |
| | | <roundcube:button type="input" command="list" class="button" label="cancel" tabindex="11" /> |
| | | </div> |
| | | <div id="compose-editorfooter"> |
| | | <span id="spellcheck-control" style="margin-right:10px"></span> |
| | | <roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" /> |
| | | <span> |
| | | <label><roundcube:label name="editortype" /></label> |
| | |
| | | </table> |
| | | </div> |
| | | |
| | | <div id="spellmenu" class="popupmenu selectable"></div> |
| | | |
| | | </form> |
| | | |
| | | <roundcube:object name="composeAttachmentForm" id="attachment-form" attachmentFieldSize="40" class="popupmenu" /> |
| | |
| | | |
| | | #composebody { |
| | | position: absolute; |
| | | top: 24px; |
| | | top: 1px; |
| | | left: 0; |
| | | bottom: 0; |
| | | width: 99%; |
| | | border: 0; |
| | | border-radius: 0; |
| | | padding: 8px 0 8px 8px; |
| | | box-shadow: none; |
| | | resize: none; |
| | |
| | | border-left: 1px solid #ddd; |
| | | padding: 8px; |
| | | overflow: auto; |
| | | } |
| | | |
| | | #spellcheck-control { |
| | | margin: 6px 8px; |
| | | text-align: right; |
| | | } |
| | | |
| | | .defaultSkin table.mceLayout, |
| | |
| | | } |
| | | |
| | | .toolbar a.button.spellcheck { |
| | | background-position: center -930px; |
| | | min-width: 64px; |
| | | background-position: left -930px; |
| | | } |
| | | |
| | | .toolbar a.button.insertsig { |
| | |
| | | background: linear-gradient(top, #00aad6 0%, #008fc9 100%); |
| | | } |
| | | |
| | | ul.toolbarmenu.iconized li a { |
| | | ul.toolbarmenu.iconized li a, |
| | | ul.toolbarmenu.selectable li a { |
| | | padding-left: 30px; |
| | | } |
| | | |
| | | ul.toolbarmenu.selectable li a.selected { |
| | | background: url(images/messages.png) 4px -27px no-repeat; |
| | | } |
| | | |
| | | ul.toolbarmenu li label { |
| | | display: block; |
| | | color: #fff; |
| | |
| | | <head> |
| | | <title><roundcube:object name="pagetitle" /></title> |
| | | <roundcube:include file="/includes/links.html" /> |
| | | <roundcube:if condition="config:enable_spellcheck" /> |
| | | <link rel="stylesheet" type="text/css" href="/googiespell.css" /> |
| | | <roundcube:endif /> |
| | | </head> |
| | | <body class="noscroll"> |
| | | |
| | |
| | | <!-- toolbar --> |
| | | <div id="messagetoolbar" class="fullwidth"> |
| | | <div id="mailtoolbar" class="toolbar"> |
| | | <roundcube:button command="spellcheck" type="link" class="button spellcheck disabled" classAct="button spellcheck" classSel="button spellcheck pressed" label="spellcheck" title="checkspelling" /> |
| | | <roundcube:if condition="config:enable_spellcheck" /> |
| | | <span class="dropbutton"> |
| | | <roundcube:button command="spellcheck" type="link" class="button spellcheck disabled" classAct="button spellcheck" classSel="button spellcheck pressed" label="spellcheck" title="checkspelling" /> |
| | | <span class="dropbuttontip" id="spellmenulink" onclick="UI.show_popup('spellmenu');return false"></span> |
| | | </span> |
| | | <roundcube:endif /> |
| | | <roundcube:button name="addattachment" type="link" class="button attach" classAct="button attach" classSel="button attach pressed" label="attach" title="addattachment" onclick="UI.show_uploadform();return false" /> |
| | | <roundcube:button command="insert-sig" type="link" class="button insertsig disabled" classAct="button insertsig" classSel="button insertsig pressed" label="signature" title="insertsignature" /> |
| | | <roundcube:container name="toolbar" id="compose-toolbar" /> |
| | |
| | | <!-- message compose body --> |
| | | <div id="composeview-bottom"> |
| | | <div id="composebodycontainer"> |
| | | <div id="spellcheck-control"></div> |
| | | <roundcube:object name="composeBody" id="composebody" form="form" cols="70" rows="20" tabindex="9" /> |
| | | </div> |
| | | <div id="compose-attachments" class="rightcol"> |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <div id="spellmenu" class="popupmenu"></div> |
| | | |
| | | <roundcube:include file="/includes/footer.html" /> |
| | | |
| | | </body> |
| | |
| | | groupmenu: { above:1 }, |
| | | mailboxmenu: { above:1 }, |
| | | composeoptionsmenu: { editable:1, overlap:1 }, |
| | | spellmenu: { callback: spellmenu }, |
| | | // toggle: #1486823, #1486930 |
| | | 'attachment-form': { editable:1, above:1, toggle:!bw.ie&&!bw.linux }, |
| | | 'upload-form': { editable:1, toggle:!bw.ie&&!bw.linux } |
| | |
| | | |
| | | bottom.css('height', (form.height() - bottom.position().top) + 'px'); |
| | | |
| | | w = body.parent().width() - 6; |
| | | h = body.parent().height() - 36; |
| | | w = body.parent().width() - 5; |
| | | h = body.parent().height() - 16; |
| | | body.width(w).height(h); |
| | | |
| | | if (window.tinyMCE && tinyMCE.get('composebody')) { |
| | | $('#composebody_tbl').width((w+10)+'px').height('').css('margin-top', '1px'); |
| | | $('#composebody_ifr').width((w+10)+'px').height((h-22)+'px'); |
| | | $('#composebody_tbl').width((w+8)+'px').height('').css('margin-top', '1px'); |
| | | $('#composebody_ifr').width((w+8)+'px').height((h-40)+'px'); |
| | | } |
| | | else { |
| | | $('#googie_edit_layer').height(h+'px'); |
| | |
| | | $('select').css('visibility', show?'hidden':'inherit'); |
| | | $('select', obj).css('visibility', 'inherit'); |
| | | } |
| | | |
| | | |
| | | return show; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | function spellmenu(show) |
| | | { |
| | | var link, li, |
| | | lang = rcmail.spellcheck_lang(), |
| | | menu = popups.spellmenu, |
| | | ul = $('ul', menu); |
| | | |
| | | if (!ul.length) { |
| | | ul = $('<ul class="toolbarmenu selectable">'); |
| | | |
| | | for (i in rcmail.env.spell_langs) { |
| | | li = $('<li>'); |
| | | link = $('<a href="#">').text(rcmail.env.spell_langs[i]) |
| | | .addClass('active').data('lang', i) |
| | | .click(function() { |
| | | rcmail.spellcheck_lang_set($(this).data('lang')); |
| | | }); |
| | | |
| | | link.appendTo(li); |
| | | li.appendTo(ul); |
| | | } |
| | | |
| | | ul.appendTo(menu); |
| | | } |
| | | |
| | | // select current language |
| | | $('li', ul).each(function() { |
| | | var el = $('a', this); |
| | | if (el.data('lang') == lang) |
| | | el.addClass('selected'); |
| | | else if (el.hasClass('selected')) |
| | | el.removeClass('selected'); |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * |
| | | */ |