diff --git a/.gitignore b/.gitignore index c88cfb29614..dbdbc28ef74 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ program/js/jquery.min.js program/js/jstz.min.js program/js/publickey.js program/js/tinymce/ +**/*.min.js # eslint dependencies /node_modules diff --git a/index.php b/index.php index 83d9be2f9e9..5cb04c169fe 100644 --- a/index.php +++ b/index.php @@ -226,7 +226,7 @@ } if ($RCMAIL->output->ajax_call || $RCMAIL->output->get_env('framed')) { - $RCMAIL->output->command('session_error', $RCMAIL->url(['_err' => 'session'])); + $RCMAIL->output->add_js_call('session_error', $RCMAIL->url(['_err' => 'session'])); $RCMAIL->output->send('iframe'); } diff --git a/installer/client.js b/installer/client.js index 7bfb7c1e1a4..1d8e7b30d1c 100644 --- a/installer/client.js +++ b/installer/client.js @@ -45,3 +45,35 @@ function removehostfield(row) { var container = document.getElementById('defaulthostlist'); container.removeChild(row); } + +function addOnclickCallback(id, callback) { + var elem = document.getElementById(id); + if (!elem) { + console.error('No element found with ID "' + id + '", cannot add callback!'); + return false; + } + elem.addEventListener('click', callback); +} + +document.addEventListener('DOMContentLoaded', function () { + addOnclickCallback('button-save-config', function () { + document.getElementById('getconfig_form').submit(); + }); + + addOnclickCallback('button-download-config', function () { + location.href = 'index.php?_getconfig=1'; + }); + + addOnclickCallback('button-continue-step-3', function () { + location.href = './index.php?_step=3'; + }); + + addOnclickCallback('remove-host-field', function (event) { + removehostfield(event.target.parentNode); + return false; + }); + + addOnclickCallback('add-host-field', function () { + addhostfield(); + }); +}); diff --git a/installer/config.php b/installer/config.php index 02e6498686f..8f2c3d5dfe9 100644 --- a/installer/config.php +++ b/installer/config.php @@ -42,13 +42,13 @@ echo ''; $button_txt = html::quote('Save in ' . $dir); - $save_button = ' '; + $save_button = ' '; } echo '

Copy or download the following configuration and save it'; echo ' as config.inc.php within the ' . RCUBE_CONFIG_DIR . ' directory of your Roundcube installation.
'; echo ' Make sure that there are no characters before the <?php bracket when saving the file.'; - echo ' '; + echo ' '; echo $save_button; if ($RCI->legacy_config) { @@ -65,7 +65,7 @@ echo '

Of course there are more options to configure. Have a look at the defaults.inc.php file or visit Howto_Config to find out.

'; - echo '

'; + echo '

'; // echo ''; echo "\n
\n"; @@ -327,14 +327,14 @@ foreach ($default_hosts as $host) { echo '
' . $text_imaphost->show($host); if ($i++ > 0) { - echo 'remove'; + echo 'remove'; } echo '
'; } ?> -
add
+
add
The IMAP host(s) chosen to perform the log-in

Leave blank to show a textbox at login. To use SSL/STARTTLS connection add ssl:// or tls:// prefix. It can also contain the port number, e.g. tls://imap.domain.tld:143. diff --git a/plugins/acl/acl.php b/plugins/acl/acl.php index 20aff988d1f..d86f750b222 100644 --- a/plugins/acl/acl.php +++ b/plugins/acl/acl.php @@ -135,7 +135,7 @@ public function acl_autocomplete() $users = array_values($keys); } - $this->rc->output->command('ksearch_query_results', $users, $search, $reqid); + $this->rc->output->add_js_call('ksearch_query_results', $users, $search, $reqid); $this->rc->output->send(); } @@ -533,7 +533,7 @@ private function action_save() if ($user != $self && $username != $self) { if ($this->rc->storage->set_acl($mbox, $user, $acl)) { $display = $this->resolve_acl_identifier($username, $title); - $this->rc->output->command('acl_update', [ + $this->rc->output->add_js_call('acl_update', [ 'id' => rcube_utils::html_identifier($user), 'username' => $username, 'title' => $title, @@ -566,7 +566,7 @@ private function action_delete() foreach ($user as $u) { $u = trim($u); if ($this->rc->storage->delete_acl($mbox, $u)) { - $this->rc->output->command('acl_remove_row', rcube_utils::html_identifier($u)); + $this->rc->output->add_js_call('acl_remove_row', rcube_utils::html_identifier($u)); } else { $error = true; } @@ -599,7 +599,7 @@ private function action_list() $out = preg_replace(['/^]+>/', '/<\/table>$/'], '', $out); - $this->rc->output->command('acl_list_update', $out); + $this->rc->output->add_js_call('acl_list_update', $out); } /** diff --git a/plugins/acl/skins/elastic/templates/table.html b/plugins/acl/skins/elastic/templates/table.html index 0a4b581337e..84032704036 100644 --- a/plugins/acl/skins/elastic/templates/table.html +++ b/plugins/acl/skins/elastic/templates/table.html @@ -18,7 +18,7 @@

- + diff --git a/plugins/archive/archive.php b/plugins/archive/archive.php index e9178b97ada..1034a2c4c99 100644 --- a/plugins/archive/archive.php +++ b/plugins/archive/archive.php @@ -227,7 +227,7 @@ public function move_messages() // @phpstan-ignore-next-line if ($this->result['error']) { if (!$from_show_action) { - $rcmail->output->command('list_mailbox'); + $rcmail->output->add_js_call('list_mailbox'); } $rcmail->output->show_message($this->gettext('archiveerror'), 'warning'); @@ -236,7 +236,7 @@ public function move_messages() if (!empty($_POST['_refresh'])) { // FIXME: send updated message rows instead of reloading the entire list - $rcmail->output->command('refresh_list'); + $rcmail->output->add_js_call('refresh_list'); $addrows = false; } else { $addrows = true; @@ -249,9 +249,9 @@ public function move_messages() if ($from_show_action) { if ($next = rcube_utils::get_input_string('_next_uid', rcube_utils::INPUT_GPC)) { - $rcmail->output->command('show_message', $next); + $rcmail->output->add_js_call('show_message', $next); } else { - $rcmail->output->command('command', 'list'); + $rcmail->output->add_js_call('command', 'list'); } $rcmail->output->send(); @@ -287,8 +287,8 @@ public function move_messages() $rcmail->output->set_env('current_page', $page); $rcmail->output->set_env('pagecount', $pages); $rcmail->output->set_env('exists', $exists); - $rcmail->output->command('set_quota', rcmail_action::quota_content(null, $quota_root)); - $rcmail->output->command('set_rowcount', rcmail_action_mail_index::get_messagecount_text($msg_count), $mbox); + $rcmail->output->add_js_call('set_quota', rcmail_action::quota_content(null, $quota_root)); + $rcmail->output->add_js_call('set_rowcount', rcmail_action_mail_index::get_messagecount_text($msg_count), $mbox); if ($threading) { $count = rcube_utils::get_input_string('_count', rcube_utils::INPUT_POST); @@ -403,7 +403,7 @@ public function prefs_table($args) 'maxlength' => 30, 'folder_filter' => 'mail', 'folder_rights' => 'w', - 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')", + 'data-onchange' => ['reset_value_if_inbox', '__THIS__'], 'class' => 'custom-select', ]); } else { diff --git a/plugins/enigma/enigma.js b/plugins/enigma/enigma.js index 865380d8cd7..fc745fe709c 100644 --- a/plugins/enigma/enigma.js +++ b/plugins/enigma/enigma.js @@ -567,14 +567,15 @@ rcube_webmail.prototype.enigma_compose_handler = function (props) { }; // Import attached keys/certs file -rcube_webmail.prototype.enigma_import_attachment = function (mime_id) { +$('[data-event-handle="enigma_import_attachment"]').on('click', function (event) { + var mime_id = event.target.dataset.part; var lock = this.set_busy(true, 'loading'), post = { _uid: this.env.uid, _mbox: this.env.mailbox, _part: mime_id }; this.http_post('plugin.enigmaimport', post, lock); return false; -}; +}); // password request popup rcube_webmail.prototype.enigma_password_request = function (data) { @@ -745,3 +746,16 @@ rcube_webmail.prototype.enigma_find_publickey = function (email) { } ); }; + +// Some event handlers. +$('[data-event-handle="enigma_import_upload"]').on('click', function (event) { + return window.rcmail.command('plugin.enigma-import', '', event.target, event); +}); + +$('[data-event-handle="enigma_import_search"]').on('click', function (event) { + return window.rcmail.command('plugin.enigma-import-search', '', event.target, event); +}); + +$('[data-event-handle="enigma_import_search"]').on('click', function (event) { + window.rcmail.command('menu-open', 'enigmamenu', event.target, event); +}); diff --git a/plugins/enigma/lib/enigma_ui.php b/plugins/enigma/lib/enigma_ui.php index 1eea580cace..723f6b0f014 100644 --- a/plugins/enigma/lib/enigma_ui.php +++ b/plugins/enigma/lib/enigma_ui.php @@ -174,7 +174,7 @@ public function password_prompt($status, $params = []) } if (preg_match('/^(send|plugin.enigmaimport|plugin.enigmakeys)$/', $this->rc->action)) { - $this->rc->output->command('enigma_password_request', $data); + $this->rc->output->add_js_call('enigma_password_request', $data); } else { $this->rc->output->set_env('enigma_password_request', $data); } @@ -254,7 +254,7 @@ private function key_list() // Add rows foreach ($list as $key) { - $this->rc->output->command('enigma_add_list_row', [ + $this->rc->output->add_js_call('enigma_add_list_row', [ 'name' => rcube::Q($key->name), 'id' => $key->id, 'flags' => $key->is_private() ? 'p' : '', @@ -266,7 +266,7 @@ private function key_list() $this->rc->output->set_env('search_request', $search); $this->rc->output->set_env('pagecount', ceil($listsize / $pagesize)); $this->rc->output->set_env('current_page', $page); - $this->rc->output->command('set_rowcount', $this->get_rowcount_text($listsize, $size, $page)); + $this->rc->output->add_js_call('set_rowcount', $this->get_rowcount_text($listsize, $size, $page)); $this->rc->output->send(); } @@ -323,7 +323,7 @@ private function key_info() $this->data = $res; } else { // error $this->rc->output->show_message('enigma.keyopenerror', 'error'); - $this->rc->output->command('parent.enigma_loadframe'); + $this->rc->output->add_js_call('parent.enigma_loadframe'); $this->rc->output->send('iframe'); } @@ -528,14 +528,14 @@ private function key_import() if (is_array($result)) { if (rcube_utils::get_input_value('_generated', rcube_utils::INPUT_POST)) { - $this->rc->output->command('enigma_key_create_success'); + $this->rc->output->add_js_call('enigma_key_create_success'); $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation'); } else { $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation', ['new' => $result['imported'], 'old' => $result['unchanged']]); if ($result['imported'] && !empty($_POST['_refresh'])) { - $this->rc->output->command('enigma_list', 1, false); + $this->rc->output->add_js_call('enigma_list', 1, false); } } } else { @@ -550,13 +550,13 @@ private function key_import() if (is_array($result)) { // reload list if any keys has been added if ($result['imported']) { - $this->rc->output->command('parent.enigma_list', 1); + $this->rc->output->add_js_call('parent.enigma_list', 1); } $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation', ['new' => $result['imported'], 'old' => $result['unchanged']]); - $this->rc->output->command('parent.enigma_import_success'); + $this->rc->output->add_js_call('parent.enigma_import_success'); } elseif ($result instanceof enigma_error && $result->getCode() == enigma_error::BADPASS) { $this->password_prompt($result); } else { @@ -611,7 +611,7 @@ public function tpl_key_import_form($attrib) $max_filesize = rcmail_action::upload_init(); $upload_button = new html_button([ 'class' => 'button import', - 'onclick' => "return rcmail.command('plugin.enigma-import','',this,event)", + 'data-event-handle' => 'enigma_import_upload', ]); $form = html::div(null, html::p(null, rcube::Q($this->enigma->gettext('keyimporttext'), 'show')) @@ -639,7 +639,7 @@ public function tpl_key_import_form($attrib) $search_button = new html_button([ 'class' => 'button search', - 'onclick' => "return rcmail.command('plugin.enigma-import-search','',this,event)", + 'data-event-handle' => 'enigma_import_search', ]); $form = html::div(null, @@ -710,7 +710,7 @@ private function key_generate() ]); if ($result instanceof enigma_key) { - $this->rc->output->command('enigma_key_create_success'); + $this->rc->output->add_js_call('enigma_key_create_success'); $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation'); } else { $this->rc->output->show_message('enigma.keygenerateerror', 'error'); @@ -820,12 +820,12 @@ private function key_delete() if ($res !== true) { $this->rc->output->show_message('enigma.keyremoveerror', 'error'); - $this->rc->output->command('enigma_list'); + $this->rc->output->add_js_call('enigma_list'); $this->rc->output->send(); } } - $this->rc->output->command('enigma_list'); + $this->rc->output->add_js_call('enigma_list'); $this->rc->output->show_message('enigma.keyremovesuccess', 'confirmation'); $this->rc->output->send(); } @@ -848,7 +848,7 @@ private function compose_ui() $this->enigma->add_button([ 'type' => 'link', 'command' => 'plugin.enigma', - 'onclick' => "rcmail.command('menu-open', 'enigmamenu', event.target, event)", + 'data-event-handle' => 'enigma_menu_open', 'class' => 'button enigma', 'title' => 'encryptionoptions', 'label' => 'encryption', @@ -1107,7 +1107,8 @@ public function message_output($p) $p['content'] = html::p(['class' => 'enigmaattachment boxinformation aligned-buttons'], html::span(null, rcube::Q($this->enigma->gettext('keyattfound'))) . html::tag('button', [ - 'onclick' => 'return ' . rcmail_output::JS_OBJECT_NAME . ".enigma_import_attachment('" . rcube::JQ($part) . "')", + 'data-event-handle' => 'enigma_import_attachment', + 'data-part' => $part, 'title' => $this->enigma->gettext('keyattimport'), 'class' => 'import btn-sm', ], rcube::Q($this->rc->gettext('import')) @@ -1190,7 +1191,7 @@ public function message_ready($p) if (!empty($msg)) { if (!empty($vars['email'])) { - $this->rc->output->command('enigma_key_not_found', [ + $this->rc->output->add_js_call('enigma_key_not_found', [ 'email' => $vars['email'], 'text' => $this->rc->gettext(['name' => $msg, 'vars' => $vars]), 'title' => $this->enigma->gettext('keynotfound'), diff --git a/plugins/help/help.php b/plugins/help/help.php index d3d1e5a0a61..3a6d3bc74ab 100644 --- a/plugins/help/help.php +++ b/plugins/help/help.php @@ -108,7 +108,8 @@ public function tablink($attrib) // so button() will translate it correctly $attrib['title'] = $attrib['label']; - $attrib['onclick'] = sprintf("return show_help_content('%s', event)", $attrib['action']); + $attrib['data-action'] = $attrib['action']; + $attrib['data-event-handle'] = 'call_show_help_content'; return $rcmail->output->button($attrib); } diff --git a/plugins/jqueryui/jqueryui.php b/plugins/jqueryui/jqueryui.php index c971bd133f2..0a3982f2e54 100644 --- a/plugins/jqueryui/jqueryui.php +++ b/plugins/jqueryui/jqueryui.php @@ -120,7 +120,8 @@ public static function miniColors() $rcube->output->include_css('plugins/jqueryui/' . $css); $rcube->output->include_script($script, 'head', false); - $rcube->output->add_script('$.fn.miniColors = $.fn.minicolors; $("input.colors").minicolors(' . $config_str . ')', 'docready'); + $rcube->output->include_script('plugins/jqueryui/js/jqueryui-minicolors-init.js'); + $rcube->output->add_js_call('jqueryui_minicolors_init', $config_str); $rcube->output->set_env('minicolors_config', $config); } diff --git a/plugins/jqueryui/js/jqueryui-minicolors-init.js b/plugins/jqueryui/js/jqueryui-minicolors-init.js new file mode 100644 index 00000000000..e5ba4c2feb5 --- /dev/null +++ b/plugins/jqueryui/js/jqueryui-minicolors-init.js @@ -0,0 +1,4 @@ +rcube_webmail.prototype.jqueryui_minicolors_init = function (config) { + $.fn.miniColors = $.fn.minicolors; + $("input.colors").minicolors(config); +} diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php index 15b468bac34..8fb92b21547 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php @@ -133,7 +133,7 @@ public function start($mode = null) // reload interface in case of possible error when specified script wasn't found (#1489412) if ($script_name !== null && !empty($list) && !in_array($script_name, $list)) { - $this->rc->output->command('reload', 500); + $this->rc->output->add_js_call('reload', 500); } // to disable 'Add filter' button set env variable @@ -306,7 +306,7 @@ public function actions() if ($result === true) { $this->rc->output->show_message('managesieve.filterdeleted', 'confirmation'); - $this->rc->output->command('managesieve_updatelist', 'del', ['id' => $fid]); + $this->rc->output->add_js_call('managesieve_updatelist', 'del', ['id' => $fid]); } else { $this->rc->output->show_message('managesieve.filterdeleteerror', 'error'); } @@ -344,7 +344,7 @@ public function actions() $result = $this->list_rules(); $this->rc->output->show_message('managesieve.moved', 'confirmation'); - $this->rc->output->command('managesieve_updatelist', 'list', + $this->rc->output->add_js_call('managesieve_updatelist', 'list', ['list' => $result, 'clear' => true, 'set' => $to]); } else { $this->rc->output->show_message('managesieve.moveerror', 'error'); @@ -367,7 +367,7 @@ public function actions() } else { $this->rc->output->show_message('managesieve.activated', 'confirmation'); } - $this->rc->output->command('managesieve_updatelist', 'update', + $this->rc->output->add_js_call('managesieve_updatelist', 'update', ['id' => $fid, 'disabled' => $rule['disabled']]); } else { if ($rule['disabled']) { @@ -386,7 +386,7 @@ public function actions() if ($result === true) { $this->rc->output->set_env('active_sets', $this->active); $this->rc->output->show_message('managesieve.setactivated', 'confirmation'); - $this->rc->output->command('managesieve_updatelist', 'setact', + $this->rc->output->add_js_call('managesieve_updatelist', 'setact', ['name' => $script_name, 'active' => true, 'all' => !$kep14]); } else { $this->rc->output->show_message('managesieve.setactivateerror', 'error'); @@ -402,7 +402,7 @@ public function actions() if ($result === true) { $this->rc->output->set_env('active_sets', $this->active); $this->rc->output->show_message('managesieve.setdeactivated', 'confirmation'); - $this->rc->output->command('managesieve_updatelist', 'setact', + $this->rc->output->add_js_call('managesieve_updatelist', 'setact', ['name' => $script_name, 'active' => false]); } else { $this->rc->output->show_message('managesieve.setdeactivateerror', 'error'); @@ -417,7 +417,7 @@ public function actions() if ($result === true) { $this->rc->output->show_message('managesieve.setdeleted', 'confirmation'); - $this->rc->output->command('managesieve_updatelist', 'setdel', ['name' => $script_name]); + $this->rc->output->add_js_call('managesieve_updatelist', 'setdel', ['name' => $script_name]); $this->rc->session->remove('managesieve_current'); } else { $this->rc->output->show_message('managesieve.setdeleteerror', 'error'); @@ -447,23 +447,23 @@ public function actions() } elseif ($action == 'list') { $result = $this->list_rules(); - $this->rc->output->command('managesieve_updatelist', 'list', ['list' => $result]); + $this->rc->output->add_js_call('managesieve_updatelist', 'list', ['list' => $result]); } elseif ($action == 'ruleadd') { $rid = rcube_utils::get_input_string('_rid', rcube_utils::INPUT_POST); $id = $this->genid(); $content = $this->rule_div($fid, $id, false, !empty($_SESSION['managesieve-compact-form'])); - $this->rc->output->command('managesieve_rulefill', $content, $id, $rid); + $this->rc->output->add_js_call('managesieve_rulefill', $content, $id, $rid); } elseif ($action == 'actionadd') { $aid = rcube_utils::get_input_string('_aid', rcube_utils::INPUT_POST); $id = $this->genid(); $content = $this->action_div($fid, $id, false); - $this->rc->output->command('managesieve_actionfill', $content, $id, $aid); + $this->rc->output->add_js_call('managesieve_actionfill', $content, $id, $aid); } elseif ($action == 'addresses') { $aid = rcube_utils::get_input_string('_aid', rcube_utils::INPUT_POST); - $this->rc->output->command('managesieve_vacation_addresses_update', $aid, $this->user_emails()); + $this->rc->output->add_js_call('managesieve_vacation_addresses_update', $aid, $this->user_emails()); } $this->rc->output->send(); @@ -515,7 +515,7 @@ public function saveraw() } } else { $this->rc->output->show_message('managesieve.setupdated', 'confirmation'); - $this->rc->output->command('parent.managesieve_updatelist', 'refresh'); + $this->rc->output->add_js_call('parent.managesieve_updatelist', 'refresh'); } $this->send(); @@ -602,7 +602,7 @@ public function save() $index = array_search($name, $list); $this->rc->output->show_message('managesieve.setcreated', 'confirmation'); - $this->rc->output->command('parent.managesieve_updatelist', 'setadd', + $this->rc->output->add_js_call('parent.managesieve_updatelist', 'setadd', ['name' => $name, 'index' => $index]); } elseif ($error) { $this->rc->output->show_message($error, 'error'); @@ -1217,9 +1217,9 @@ public function save() 'id' => $fid, 'disabled' => $this->form['disabled'], ]; - $this->rc->output->command('parent.managesieve_updatelist', isset($new) ? 'add' : 'update', $args); + $this->rc->output->add_js_call('parent.managesieve_updatelist', isset($new) ? 'add' : 'update', $args); } else { - $this->rc->output->command('managesieve_dialog_close'); + $this->rc->output->add_js_call('managesieve_dialog_close'); $this->rc->output->send('iframe'); } } else { @@ -1321,7 +1321,7 @@ public function filtersets_list($attrib, $no_env = false) 'name' => '_set', 'id' => $attrib['id'], 'class' => 'custom-select', - 'onchange' => $this->rc->task != 'mail' ? 'rcmail.managesieve_set()' : '', + 'data-onchange' => $this->rc->task != 'mail' ? ['managesieve_set'] : '', ]); if ($list) { @@ -1567,7 +1567,7 @@ public function filter_form($attrib) if ($compact) { $select = new html_select(['name' => '_join', 'id' => '_join', 'class' => 'custom-select', - 'onchange' => 'rule_join_radio(this.value)']); + 'data-onchange' => ['managesieve_rule_join_radio_with_this_value']]); foreach (['allof', 'anyof', 'any'] as $val) { $select->add($this->plugin->gettext('filter' . $val), $val); @@ -1592,7 +1592,7 @@ public function filter_form($attrib) // any, allof, anyof radio buttons $field_id = '_allof'; $input_join = new html_radiobutton(['name' => '_join', 'id' => $field_id, 'value' => 'allof', - 'onclick' => 'rule_join_radio(\'allof\')', 'class' => 'radio']); + 'data-event-handle' => 'managesieve_rule_join_radio', 'data-value' => 'allof', 'class' => 'radio']); if (isset($scr) && !$any) { $input_join = $input_join->show($scr['join'] ? 'allof' : ''); @@ -1604,7 +1604,7 @@ public function filter_form($attrib) $field_id = '_anyof'; $input_join = new html_radiobutton(['name' => '_join', 'id' => $field_id, 'value' => 'anyof', - 'onclick' => 'rule_join_radio(\'anyof\')', 'class' => 'radio']); + 'data-event-handle' => 'managesieve_rule_join_radio', 'data-value' => 'anyof', 'class' => 'radio']); if (isset($scr) && !$any) { $input_join = $input_join->show($scr['join'] ? '' : 'anyof'); @@ -1616,7 +1616,7 @@ public function filter_form($attrib) $field_id = '_any'; $input_join = new html_radiobutton(['name' => '_join', 'id' => $field_id, 'value' => 'any', - 'onclick' => 'rule_join_radio(\'any\')', 'class' => 'radio']); + 'data-event-handle' => 'managesieve_rule_join_radio', 'data-value' => 'any', 'class' => 'radio']); $input_join = $input_join->show($any ? 'any' : ''); @@ -1687,7 +1687,7 @@ public function rule_div($fid, $id, $div = true, $compact = false) // headers select $select_header = new html_select(['name' => "_header[{$id}]", 'id' => 'header' . $id, - 'onchange' => 'rule_header_select(' . $id . ')', 'class' => 'custom-select']); + 'data-onchange' => ['rule_header_select', $id]), 'class' => 'custom-select']; foreach ($this->headers as $index => $header) { $header = $this->rc->text_exists($index) ? $this->plugin->gettext($index) : $header; @@ -1872,7 +1872,7 @@ public function rule_div($fid, $id, $div = true, $compact = false) 'name' => "_rule_spamtest_op[{$id}]", 'id' => 'rule_spamtest_op' . $id, 'class' => 'input-group-prepend custom-select', - 'onchange' => 'rule_spamtest_select(' . $id . ')', + 'data-onchange' => ['rule_spamtest_select', $id], ]); $select_spamtest_op->add(rcube::Q($this->plugin->gettext('spamtestisunknown')), ''); $select_spamtest_op->add(rcube::Q($this->plugin->gettext('spamtestisgreaterthan')), 'value-gt'); @@ -1909,7 +1909,7 @@ public function rule_div($fid, $id, $div = true, $compact = false) 'name' => "_rule_mod[{$id}]", 'id' => 'rule_mod_op' . $id, 'class' => 'custom-select', - 'onchange' => 'rule_mod_select(' . $id . ')', + 'data-onchange' => ['rule_mod_select', $id], ]); $select_mod->add(rcube::Q($this->plugin->gettext('none')), ''); $select_mod->add(rcube::Q($this->plugin->gettext('address')), 'address'); @@ -1955,7 +1955,7 @@ public function rule_div($fid, $id, $div = true, $compact = false) $select_mime = new html_select([ 'name' => "_rule_mime_type[{$id}]", 'id' => 'rule_mime_type' . $id, - 'style' => 'min-width:8em', 'onchange' => 'rule_mime_select(' . $id . ')', + 'style' => 'min-width:8em', 'data-onchange' => ['rule_mime_select', $id], 'class' => 'custom-select', ]); $select_mime->add('-', ''); @@ -1994,7 +1994,7 @@ public function rule_div($fid, $id, $div = true, $compact = false) 'name' => "_rule_trans[{$id}]", 'id' => 'rule_trans_op' . $id, 'class' => 'custom-select', - 'onchange' => 'rule_trans_select(' . $id . ')', + 'data-onchange' => ['rule_trans_select', $id], ]); $select_mod->add(rcube::Q($this->plugin->gettext('text')), 'text'); $select_mod->add(rcube::Q($this->plugin->gettext('undecoded')), 'raw'); @@ -2108,25 +2108,66 @@ public function rule_div($fid, $id, $div = true, $compact = false) $out .= ''; if (!$compact) { - $out .= ''; + $out .= html::tag('td', ['class' => 'advbutton'], + html::a([ + 'href' => '#', + 'id' => "ruleadv{$id}", + 'title' => $adv_title, + 'data-id' => $id, + 'data-event-handle' => 'managesieve_rule_adv_switch', + 'class' => 'show', + ], + html::span(['class' => 'inner'], $adv_title) + ) + ); } - $out .= ''; - $out .= ''; + $out .= html::tag('td', ['class' => 'rowactions'], + html::div(['class' => 'flexbox'], $aout) + ); + $out .= html::tag('td', ['class' => 'rowtargets'], [ + $tout, + html::div([ + 'id' => "rule_advanced{$id}", + 'style' => 'display:none', + 'class' => 'advanced', + ], + $mout), + ]); + $out .= ''; $out .= '
'; - $out .= sprintf('' - . '%s', $id, $adv_title, $id, $adv_title); - $out .= '
' . $aout . '
' . $tout . "\n"; - $out .= ''; - $out .= ''; if ($compact) { - $out .= sprintf('' - . '%s', $id, $adv_title, $id, $adv_title); + $out .= html::a([ + 'href' => '#', + 'id' => "ruleadv{$id}", + 'title' => $adv_title, + 'data-id' => $id, + 'data-event-handle' => 'managesieve_rule_adv_switch', + 'class' => 'advanced show', + ], + html::span(['class' => 'inner'], $adv_title) + ); } - $out .= sprintf('' - . '%s', $id, $add_title, $id, $add_title); - $out .= sprintf('' - . '%s', $id, $del_title, $id, $rows_num < 2 ? ' disabled' : '', $del_title); + $out .= html::a([ + 'href' => '#', + 'id' => "ruleadd{$id}", + 'title' => $add_title, + 'data-id' => $id, + 'data-event-handle' => 'managesieve_ruleadd', + 'class' => 'button create add', + ], + html::span(['class' => 'inner'], $add_title) + ); + $out .= html::a([ + 'href' => '#', + 'id' => "ruledel{$id}", + 'title' => $del_title, + 'data-id' => $id, + 'data-event-handle' => 'managesieve_ruledel', + 'class' => 'button delete del ' . $rows_num < 2 ? 'disabled' : '', + ], + html::span(['class' => 'inner'], $del_title) + ); $out .= '
'; @@ -2211,7 +2252,7 @@ public function action_div($fid, $id, $div = true) 'name' => "_action_type[{$id}]", 'id' => 'action_type' . $id, 'class' => 'custom-select', - 'onchange' => "action_type_select({$id})", + 'data-onchange' => ['managesieve_action_type_select', $id], ]); if (in_array('fileinto', $this->exts)) { $select_action->add($this->plugin->gettext('messagemoveto'), 'fileinto'); @@ -2373,7 +2414,7 @@ public function action_div($fid, $id, $div = true) $out .= $this->list_input($id, 'action_addresses', $action['addresses'] ?? null, 30, false, ['class' => $this->error_class($id, 'action', 'addresses', 'action_addresses')] ) - . html::a(['href' => '#', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".managesieve_vacation_addresses({$id})"], + . html::a(['href' => '#', 'data-event-handle' => 'managesieve_vacation_addresses', 'data-id' => $id], rcube::Q($this->plugin->gettext('filladdresses'))); $out .= '
' . rcube::Q($this->plugin->gettext('vacationinterval')) . '
'; $out .= '
' . html::tag('input', [ @@ -2671,12 +2712,30 @@ public function action_div($fid, $id, $div = true) // add/del buttons $add_label = rcube::Q($this->plugin->gettext('add')); $del_label = rcube::Q($this->plugin->gettext('del')); - $out .= ''; - $out .= sprintf('' - . '%s', $id, $add_label, $id, $add_label); - $out .= sprintf('' - . '%s', $id, $del_label, $id, $rows_num < 2 ? ' disabled' : '', $del_label); - $out .= ''; + $out .= html::tag('td', ['class' => 'rowbuttons'], + html::a( + [ + 'href' => '#', + 'id' => "actionadd{$id}", + 'title' => $add_label, + 'data-id' => $id, + 'data-event-handle' => 'managesieve_actionadd', + 'class' => 'button create add', + ], + html::span(['class' => 'inner'], $add_label), + ), + html::a( + [ + 'href' => '#', + 'id' => "actiondel{$id}", + 'title' => $del_label, + 'data-id' => $id, + 'data-event-handle' => ['managesieve_actiondel', + 'class' => 'button delete del ' . ($rows_num < 2 ? 'disabled' : ''), + ], + html::span(['class' => 'inner'], $del_label), + ) + ); $out .= ''; @@ -2757,8 +2816,7 @@ protected function print_tips() return; } - $script = rcmail_output::JS_OBJECT_NAME . '.managesieve_tip_register(' . json_encode($this->tips) . ');'; - $this->rc->output->add_script($script, 'docready'); + $this->rc->output->add_js_call('managesieve_tip_register', $this->tips); } protected function list_input($id, $name, $value, $size = null, $hidden = false, $attrib = []) @@ -3255,7 +3313,7 @@ protected function match_type_selector($name, $id, $test, $rule = null, $mode = 'id' => "{$name}{$id}", 'style' => 'display:' . (!in_array($rule, ['size', 'duplicate', 'spamtest']) ? 'inline' : 'none'), 'class' => 'operator_selector col-6 custom-select', - 'onchange' => "{$name}_select(this, '{$id}')", + 'data-onchange' => ["managesieve_{$name}_select", '__THIS__', $id], ]); $select_op->add(rcube::Q($this->plugin->gettext('filtercontains')), 'contains'); diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php index ac7abe7e6a8..6afb627f2ff 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php @@ -393,12 +393,12 @@ public function vacation_form($attrib) . (!empty($this->vacation['addresses']) ? rcube::Q(implode("\n", (array) $this->vacation['addresses']), 'strict', false) : '') . ''; $status = new html_select(['name' => 'vacation_status', 'id' => 'vacation_status', 'class' => 'custom-select']); - $action = new html_select(['name' => 'vacation_action', 'id' => 'vacation_action', 'class' => 'custom-select', 'onchange' => 'vacation_action_select()']); + $action = new html_select(['name' => 'vacation_action', 'id' => 'vacation_action', 'class' => 'custom-select', 'data-onchange' => ['vacation_action_select']]); $addresses_link = new html_inputfield([ 'type' => 'button', 'href' => '#', 'class' => 'button', - 'onclick' => rcmail_output::JS_OBJECT_NAME . '.managesieve_vacation_addresses()', + 'data-event-handle' => 'managesieve_vacation_addresses', ]); $redirect = !empty($this->vacation['action']) diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js index c9b43fa6227..f9769fc1ee0 100644 --- a/plugins/managesieve/managesieve.js +++ b/plugins/managesieve/managesieve.js @@ -537,10 +537,6 @@ rcube_webmail.prototype.managesieve_save = function () { }; // Operations on filters form -rcube_webmail.prototype.managesieve_ruleadd = function (id) { - this.http_post('plugin.managesieve-action', '_act=ruleadd&_rid=' + id); -}; - rcube_webmail.prototype.managesieve_rulefill = function (content, id, after) { if (content != '') { // create new element @@ -559,22 +555,6 @@ rcube_webmail.prototype.managesieve_rulefill = function (content, id, after) { } }; -rcube_webmail.prototype.managesieve_ruledel = function (id) { - if ($('#ruledel' + id).hasClass('disabled')) { - return; - } - - this.confirm_dialog(this.get_label('managesieve.ruledeleteconfirm'), 'delete', function (e, ref) { - var row = document.getElementById('rulerow' + id); - row.parentNode.removeChild(row); - ref.managesieve_formbuttons(document.getElementById('rules')); - }); -}; - -rcube_webmail.prototype.managesieve_actionadd = function (id) { - this.http_post('plugin.managesieve-action', '_act=actionadd&_aid=' + id); -}; - rcube_webmail.prototype.managesieve_actionfill = function (content, id, after) { if (content != '') { var div = $('#actions')[0], @@ -592,18 +572,6 @@ rcube_webmail.prototype.managesieve_actionfill = function (content, id, after) { } }; -rcube_webmail.prototype.managesieve_actiondel = function (id) { - if ($('#actiondel' + id).hasClass('disabled')) { - return; - } - - this.confirm_dialog(this.get_label('managesieve.actiondeleteconfirm'), 'delete', function (e, ref) { - var row = document.getElementById('actionrow' + id); - row.parentNode.removeChild(row); - ref.managesieve_formbuttons(document.getElementById('actions')); - }); -}; - // insert rule/action row in specified place on the list rcube_webmail.prototype.managesieve_insertrow = function (div, row, after) { var node = $('#' + ($(div).attr('id') == 'rules' ? 'rulerow' : 'actionrow') + after)[0]; @@ -627,12 +595,6 @@ rcube_webmail.prototype.managesieve_formbuttons = function (div) { } }; -// update vacation addresses field with user identities -rcube_webmail.prototype.managesieve_vacation_addresses = function (id) { - var lock = this.set_busy(true, 'loading'); - this.http_post('plugin.managesieve-action', { _act: 'addresses', _aid: id }, lock); -}; - // update vacation addresses field with user identities rcube_webmail.prototype.managesieve_vacation_addresses_update = function (id, addresses) { var field = $('#vacation_addresses,#action_addresses' + (id || '')); @@ -747,6 +709,8 @@ function rule_op_select(obj, id, header) { target.style.display = obj.value.match(/^(exists|notexists)$/) || header.match(/^(size|spamtest|message)$/) ? 'none' : ''; } +rcube_webmail.prototype.managesieve_rule_op_select = rule_op_select; + function rule_trans_select(id) { var obj = document.getElementById('rule_trans_op' + id), target = document.getElementById('rule_trans_type' + id); @@ -787,22 +751,6 @@ function rule_spamtest_select(id) { $(obj)[obj.value ? 'removeClass' : 'addClass']('rounded-right'); } -function rule_join_radio(value) { - $('#rules').css('display', value == 'any' ? 'none' : 'block'); -} - -function rule_adv_switch(id, elem) { - var elem = $(elem), enabled = elem.hasClass('hide'), adv = $('#rule_advanced' + id); - - if (enabled) { - adv.get(0).style.display = 'none'; - elem.removeClass('hide').addClass('show'); - } else { - adv.get(0).style.display = ''; - elem.removeClass('show').addClass('hide'); - } -} - function rule_mime_select(id) { var elem = $('#rule_mime_type' + id), param_elem = $('#rule_mime_param' + id + '_list'); @@ -847,6 +795,8 @@ function action_type_select(id) { } } +rcube_webmail.prototype.managesieve_action_type_select = action_type_select; + function vacation_action_select() { var selected = $('#vacation_action').val(); @@ -1140,7 +1090,7 @@ var cmeditor; function cmCreateErrorElem(msg) { var marker = document.createElement('div'); marker.style.color = '#822'; - marker.innerHTML = '●'; + marker.innerText = '●'; marker.title = msg; return marker; @@ -1283,3 +1233,77 @@ rcube_webmail.prototype.managesieve_dialog_resize = function (o) { dialog.dialog('option', { height: Math.min(h - 20, height + 120), width: Math.min(w - 20, width + 65) }); }; + +// Some event handlers. +window.rcmail.addEventListener('init', function () { + + $('[data-event-handle="managesieve_switch_nav_list"]').on('click', function (event) { + UI.switch_nav_list(event.target); + }); + + $('[data-event-handle="managesieve_ruleadd"]').on('click', function (event) { + const id = event.target.dataset.id; + this.http_post('plugin.managesieve-action', '_act=ruleadd&_rid=' + id); + return false; + }); + + $('[data-event-handle="managesieve_ruledel"]').on('click', function (event) { + const id = event.target.dataset.id; + if ($('#ruledel' + id).hasClass('disabled')) { + return; + } + + this.confirm_dialog(this.get_label('managesieve.ruledeleteconfirm'), 'delete', function (e, ref) { + var row = document.getElementById('rulerow' + id); + row.parentNode.removeChild(row); + ref.managesieve_formbuttons(document.getElementById('rules')); + }); + }); + + $('[data-event-handle="managesieve_actionadd"]').on('click', function (event) { + const id = event.target.dataset.id; + this.http_post('plugin.managesieve-action', '_act=actionadd&_aid=' + id); + }); + + $('[data-event-handle="managesieve_actiondel"]').on('click', function (event) { + const id = event.target.dataset.id; + if ($('#actiondel' + id).hasClass('disabled')) { + return; + } + + this.confirm_dialog(this.get_label('managesieve.actiondeleteconfirm'), 'delete', function (e, ref) { + var row = document.getElementById('actionrow' + id); + row.parentNode.removeChild(row); + ref.managesieve_formbuttons(document.getElementById('actions')); + }); + }); + + // update vacation addresses field with user identities + $('[data-event-handle="managesieve_vacation_addresses"]').on('click', function (event) { + const id = event.target.dataset.id; + var lock = window.rcmail.set_busy(true, 'loading'); + window.rcmail.http_post('plugin.managesieve-action', { _act: 'addresses', _aid: id }, lock); + }); + + $('data-event-handle="managesieve_rule_join_radio"]').on('click', function (event) { + const value = event.target.dataset.value; + $('#rules').css('display', value == 'any' ? 'none' : 'block'); + }); + + $('data-event-handle="managesieve_rule_adv_switch"]').on('click', function (event) { + var elem = event.target; + var id = elem.dataset.id; + var elem = $(elem), enabled = elem.hasClass('hide'), adv = $('#rule_advanced' + id); + + if (enabled) { + adv.get(0).style.display = 'none'; + elem.removeClass('hide').addClass('show'); + } else { + adv.get(0).style.display = ''; + elem.removeClass('show').addClass('hide'); + } + + return false; + }); + +}); diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php index 1e160b60f83..da38fff2d72 100644 --- a/plugins/managesieve/managesieve.php +++ b/plugins/managesieve/managesieve.php @@ -206,7 +206,7 @@ public function mail_headers($args) $headers = $this->parse_headers($args['headers']); if ($this->rc->action == 'preview') { - $this->rc->output->command('parent.set_env', ['sieve_headers' => $headers]); + $this->rc->output->add_js_call('parent.set_env', ['sieve_headers' => $headers]); } else { $this->rc->output->set_env('sieve_headers', $headers); } @@ -228,7 +228,7 @@ public function managesieve_actions() $headers = $this->parse_headers($message->headers); $this->rc->output->set_env('sieve_headers', $headers); - $this->rc->output->command('managesieve_create', true); + $this->rc->output->add_js_call('managesieve_create', true); $this->rc->output->send(); } diff --git a/plugins/managesieve/skins/elastic/templates/managesieve.html b/plugins/managesieve/skins/elastic/templates/managesieve.html index e3201f89326..7ecfeb874e3 100644 --- a/plugins/managesieve/skins/elastic/templates/managesieve.html +++ b/plugins/managesieve/skins/elastic/templates/managesieve.html @@ -18,7 +18,7 @@

:

- @@ -46,7 +46,7 @@

- + diff --git a/skins/elastic/templates/compose.html b/skins/elastic/templates/compose.html index 0f7cad8caf0..218cfb04704 100644 --- a/skins/elastic/templates/compose.html +++ b/skins/elastic/templates/compose.html @@ -21,7 +21,7 @@

- +
@@ -78,7 +78,7 @@

@@ -138,7 +138,7 @@

- " tabindex="1"> + " tabindex="1"> " tabindex="1"> @@ -152,10 +152,10 @@

- " tabindex="1"> + " tabindex="1"> - + @@ -166,10 +166,10 @@

- " tabindex="1"> + " tabindex="1"> - + @@ -180,10 +180,10 @@

- " tabindex="1"> + " tabindex="1"> - + @@ -194,10 +194,10 @@

- " tabindex="1"> + " tabindex="1"> - + @@ -248,7 +248,7 @@

- + diff --git a/skins/elastic/templates/folders.html b/skins/elastic/templates/folders.html index c3632744b24..ddfc9ebaa0a 100644 --- a/skins/elastic/templates/folders.html +++ b/skins/elastic/templates/folders.html @@ -19,7 +19,7 @@

- +
diff --git a/skins/elastic/templates/includes/layout.html b/skins/elastic/templates/includes/layout.html index 90a83741475..d4ed18fd7c8 100644 --- a/skins/elastic/templates/includes/layout.html +++ b/skins/elastic/templates/includes/layout.html @@ -29,15 +29,7 @@ - + action-"> diff --git a/skins/elastic/templates/includes/mail-menu.html b/skins/elastic/templates/includes/mail-menu.html index b50d7810154..1f9cd102150 100644 --- a/skins/elastic/templates/includes/mail-menu.html +++ b/skins/elastic/templates/includes/mail-menu.html @@ -64,7 +64,7 @@

+ name="messageimport" data-event-handle="ui_import_dialog" /> diff --git a/skins/elastic/templates/includes/menu.html b/skins/elastic/templates/includes/menu.html index 352eeb58a82..62063ddddfb 100644 --- a/skins/elastic/templates/includes/menu.html +++ b/skins/elastic/templates/includes/menu.html @@ -34,7 +34,7 @@

+ class="about" innerClass="inner" data-event-handle="ui_about_dialog" /> diff --git a/skins/elastic/templates/mail.html b/skins/elastic/templates/mail.html index 2e483e9d6e1..b6ba070b805 100644 --- a/skins/elastic/templates/mail.html +++ b/skins/elastic/templates/mail.html @@ -96,7 +96,7 @@

- +
@@ -132,8 +132,8 @@

@@ -152,7 +152,7 @@