/**
* Mél keyboard shortcuts
*
* Based on Kolab keyboard shortcuts plugin by Aleksander Machniak <machniak@kolabsys.com>
*
* @licstart The following is the entire license notice for the
* JavaScript code in this file.
*
* Copyright (C) 2016, PNE Annuaire et Messagerie/MEDDE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @licend The above is the entire license notice
* for the JavaScript code in this file.
*/
/**
* Configuration des raccourcis clavier basé sur Thunderbird
*
* voir : https://support.mozilla.org/en-US/kb/keyboard-shortcuts
*/
var mel_shortcuts_press = {
///// Receiving and reading messages
'mail.expand-all-threads': {
keypress: 42, // *
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
return rcmail.command('expand-all', '', e.target, e);
}
},
'mail.collapse-all-threads': {
keypress: 92, // \
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
return rcmail.command('collapse-all', '', e.target, e);
}
},
};
var mel_shortcuts_down = {
///// Starting a new message
'mail.new-message' : {
keydown: 78, // Ctrl + Shift + N
ctrl: true,
shift: true,
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) { return rcmail.command('compose', '', e.target, e); }
},
'mail.new-message-bis' : {
keydown: 77, // Ctrl + Shift + M
ctrl: true,
shift: true,
active: function(e) { return true; },
action: function(e) { return rcmail.command('compose', '', e.target, e); }
},
'mail.reply': {
keydown: 82, // Ctrl + R
ctrl: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['reply']; },
action: function(e) {
return rcmail.command('reply', '', e.target, e);
}
},
'mail.replyall': {
keydown: 82, // Ctrl + Shift + R
ctrl: true,
shift: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['reply-all']; },
action: function(e) {
return rcmail.command('reply-all', 'sub', e.target, e);
}
},
'mail.replylist': {
keydown: 76, // Ctrl + Shift + L
ctrl: true,
shift: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['reply-list']; },
action: function(e) {
return rcmail.command('reply-list', '', e.target, e);
}
},
'mail.forward-attachment': {
keydown: 76, // Ctrl + L
ctrl: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['forward-attachment']; },
action: function(e) {
return rcmail.command('forward-attachment', 'sub', e.target, e);
}
},
'mail.forward-inline': {
keydown: 70, // Ctrl + Shift + F
ctrl: true,
shift: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['forward-inline']; },
action: function(e) {
return rcmail.command('forward-inline', 'sub', e.target, e);
}
},
///// Receiving and reading messages
'mail.refresh': {
keydown: 90, // Ctrl + Shift + Z
ctrl: true,
shift: true,
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) { return rcmail.command('checkmail', '', e.target, e); }
},
'mail.expand-thread': {
keydown: 39, // ->
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
if (rcmail.message_list) {
var row, uid = rcmail.message_list.get_single_selection();
if (uid && (row = rcmail.message_list.rows[uid])) {
rcmail.message_list.expand_all(row);
}
}
}
},
'mail.collapse-thread': {
keydown: 37, // <-
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
if (rcmail.message_list) {
var row, uid = rcmail.message_list.get_single_selection();
if (uid && (row = rcmail.message_list.rows[uid])) {
rcmail.message_list.collapse_all(row);
}
}
}
},
///// Managing your messages
'mail.message-source': {
keydown: 85, // Ctrl + U
ctrl: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['viewsource']; },
action: function(e) {
return rcmail.commands['viewsource'] ? rcmail.command('viewsource', '', e.target, e) : false;
}
},
'mail.select-all': {
keydown: 65, // Ctrl + A
ctrl: true,
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) { return rcmail.command('select-all', '', e.target, e); }
},
'mail.copy': {
keydown: 67, // Ctrl + Shift + C
ctrl: true,
shift: true,
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
e = mel_shortcuts_menu_target(e);
e.rcmail.command('copy', '', e.target, e);
e.target.remove();
}
},
'mail.move': {
keydown: 77, // Ctrl + M
ctrl: true,
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
e = mel_shortcuts_menu_target(e);
e.rcmail.command('move', '', e.target, e);
e.target.remove();
}
},
'mail.next-msg': {
keydown: 78, // n
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
if (rcmail.message_list)
return rcmail.message_list.select_next();
else
return rcmail.command('nextmessage', '', '', e);
}
},
'mail.prev-msg': {
keydown: 80, // p
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
if (rcmail.message_list)
return rcmail.message_list.use_arrow_key(38, false);
else
return rcmail.command('previousmessage', '', '', e);
}
},
////// Tagging and marking your messages
'mail.mark-as-read-unread': {
keydown: 77, // m
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
var list = rcmail.message_list;
if (list) {
var flag = 'unread', a_uids = list.get_selection();
for (n=0, len=a_uids.length; n<len; n++) {
id = a_uids[n];
if (list.rows[id].unread) {
flag = 'read';
break;
}
}
return rcmail.command('mark', flag, a_uids, e)
}
}
},
'mail.mark-as-read': {
keydown: 82, // r
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['mark']; },
action: function(e) {
return rcmail.command('mark', 'read', e.target, e)
}
},
'mail.add-remove-star': {
keydown: 83, // s
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
var list = rcmail.message_list;
if (list) {
var flag = 'unflagged', a_uids = list.get_selection();
for (n=0, len=a_uids.length; n<len; n++) {
id = a_uids[n];
if (!list.rows[id].flagged) {
flag = 'flagged';
break;
}
}
return rcmail.command('mark', flag, a_uids, e)
}
}
},
////// Mail compose
'mail.send': {
keydown: 13, // Ctrl + Enter
ctrl: true,
active: function(e) { return rcmail.task == 'mail'; },
action: function(e) {
return rcmail.commands['send'] ? rcmail.command('send', '', e.target, e) : false;
}
},
//////// Calendar
'calendar.new-event': {
keydown: 73, // Ctrl + I
ctrl: true,
active: function(e) { return rcmail.commands['add-event-from-shortcut'] || rcmail.commands['addevent']; },
action: function(e) {
return rcmail.commands['add-event-from-shortcut'] ? rcmail.command('add-event-from-shortcut', '', e.target, e) : rcmail.command('addevent', '', e.target, e);
}
},
'calendar.prevday': {
keydown: 78, // Shift + N
shift: true,
active: function(e) { return rcmail.task == 'calendar' && rcmail.commands['prevDay']; },
action: function(e) {
return rcmail.command('prevDay', '', e.target, e);
}
},
'calendar.today': {
keydown: 35, // Alt + End
alt: true,
active: function(e) { return rcmail.task == 'calendar' && rcmail.commands['today']; },
action: function(e) {
return rcmail.command('today', '', e.target, e);
}
},
'calendar.nextday': {
keydown: 80, // Shift + P
shift: true,
active: function(e) { return rcmail.task == 'calendar' && rcmail.commands['nextDay']; },
action: function(e) {
return rcmail.command('nextDay', '', e.target, e);
}
},
//////// Escape
'escape': {
keydown: 27, // Escape
active: function(e) { return true; },
action: function(e) {
if (rcmail.task == 'mail' && rcmail.env.action == 'compose') {
return rcmail.commands['list'] ? rcmail.command('list', '', e.target, e) : false;
}
else if (rcmail.task == 'calendar' && rcmail.env.action == 'print') {
return window.close();
}
}
},
//////// Menu switch
'menu.mail': {
keydown: 49, // Ctrl + Shift + 1
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'mail'; },
action: function(e) {
return rcmail.command('switch-task', 'mail', e.target, e);
}
},
'menu.addressbook': {
keydown: 50, // Ctrl + Shift + 2
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'addressbook'; },
action: function(e) {
return rcmail.command('switch-task', 'addressbook', e.target, e);
}
},
'menu.calendar': {
keydown: 51, // Ctrl + Shift + 3
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'calendar'; },
action: function(e) {
return rcmail.command('switch-task', 'calendar', e.target, e);
}
},
'menu.discussion': {
keydown: 52, // Ctrl + Shift + 4
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'discussion'; },
action: function(e) {
return rcmail.command('switch-task', 'discussion', e.target, e);
}
},
'menu.sondage': {
keydown: 53, // Ctrl + Shift + 5
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'sondage'; },
action: function(e) {
return rcmail.command('switch-task', 'sondage', e.target, e);
}
},
'menu.tasks': {
keydown: 55, // Ctrl + Shift + 7
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'tasks'; },
action: function(e) {
return rcmail.command('switch-task', 'tasks', e.target, e);
}
},
'menu.stockage': {
keydown: 54, // Ctrl + Shift + 6
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'stockage'; },
action: function(e) {
return rcmail.command('switch-task', 'stockage', e.target, e);
}
},
'menu.settings': {
keydown: 56, // Ctrl + Shift + 8
ctrl: true,
shift: true,
active: function(e) { return rcmail.task != 'settings' || rcmail.env.action == 'plugin.mel_moncompte'; },
action: function(e) {
return rcmail.command('switch-task', 'settings', e.target, e);
}
},
//////// Save
'save': {
keydown: 83, // Ctrl + S
ctrl: true,
active: function(e) { return rcmail.task == 'mail' || $('#eventedit').length && $('#eventedit').is(':visible'); },
action: function(e) {
if ($('#eventedit').length && $('#eventedit').is(':visible')) {
$('#eventedit').parent().parent().find('.mainaction').click();
}
else if (rcmail.env.action == 'list' || rcmail.env.action == 'show' || rcmail.env.action == '') {
return rcmail.commands['download'] ? rcmail.command('download', '', e.target, e) : false;
}
else if (rcmail.env.action == 'compose') {
return rcmail.commands['savedraft'] ? rcmail.command('savedraft', '', e.target, e) : false;
}
}
},
/////// Edit
'edit': {
keydown: 69, // Ctrl + E
ctrl: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.commands['edit'] || rcmail.task == 'calendar' && $('#eventshow').length && $('#eventshow').is(':visible'); },
action: function(e) {
if (rcmail.task == 'calendar' && $('#eventshow').length && $('#eventshow').is(':visible')) {
$('#eventshow').parent().find('.ui-dialog-buttonset .ui-button').click();
}
else if (rcmail.task == 'mail' && rcmail.commands['edit']) {
var mode = rcmail.env.mailbox == rcmail.env.drafts_mailbox ? '' : 'new';
return rcmail.command('edit', mode, e.target, e);
}
}
},
//////// Delete
'delete': {
keydown: 46, // Delete
active: function(e) { return rcmail.task == 'mail' && rcmail.env.action == 'preview' || rcmail.task == 'calendar' && $('#eventshow').length && $('#eventshow').is(':visible'); },
action: function(e) {
if (rcmail.task == 'calendar' && $('#eventshow').length && $('#eventshow').is(':visible')) {
$('#eventshow').parent().find('.delete').click();
}
else if (rcmail.task == 'mail' && rcmail.env.action == 'preview') {
window.parent.rcmail.command('delete', '', e.target, e);
}
}
},
//////// Shift + Delete
'shift_delete': {
keydown: 46, // Shift + Delete
shift: true,
active: function(e) { return rcmail.task == 'mail' && rcmail.env.action == 'preview' },
action: function(e) {
if (confirm(window.parent.rcmail.get_label('deletemessagesconfirm')))
window.parent.rcmail.permanently_remove_messages();
}
},
//////// Print
'print': {
keydown: 80, // Ctrl + P
ctrl: true,
active: function(e) { return rcmail.commands['print']; },
action: function(e) {
return rcmail.commands['print'] ? rcmail.command('print', '', e.target, e) : false;
}
},
//////// Search
'search.focus': {
keydown: 75, // Ctrl + Shift + K
ctrl: true,
shift: true,
active: function(e) { return true; },
action: function(e) {
if (!rcmail.is_framed())
$('#quicksearchbox').focus();
else if (window.parent && window.parent.$)
window.parent.$('#quicksearchbox').focus();
}
},
};
// create a fake element centered on the page,
// so folder selector popupup appears in the center
var mel_shortcuts_menu_target = function(e)
{
var rc, target,
css = {visibility: 'hidden', width: 10, height: 10, margin: 'auto'};
if (rcmail.is_framed()) {
rc = parent.rcmail;
target = parent.$('<div>').css(css).appendTo(parent.$('body'));
}
else {
rc = rcmail;
target = $('<div>').css(css).appendTo($('body'));
}
e.target = target;
e.rcmail = rc;
return e;
};
var mel_shortcuts_keypress = function(e)
{
var i, handler, key = e.which;
// Detect escape
if (e.which == 0) {
key = e.keyCode;
}
// console.log("### mel_shortcuts_keypress");
// console.log(e.which);
// console.log(e.keyCode);
// do nothing on input elements if no ctrl
if ($(e.target).is('textarea,input')) {
return true;
}
// do nothing if any popup menu is displayed
if ($('.popupmenu:visible').length) {
return true;
}
for (i in mel_shortcuts_press) {
handler = mel_shortcuts_press[i];
// check if presses key(s) match
if (handler.keypress == key) {
// ... and action is active here
if (handler.active(e)) {
// execute action, the real check if action is active
// will be done in .action() or in rcmail.command()
handler.action(e);
e.preventDefault();
e.stopImmediatePropagation();
return false;
}
// we can break here, there can be only one handler
// for the specified shortcut
break;
}
}
return true;
};
var mel_shortcuts_keydown = function(e)
{
var i, handler, key = e.which, alt = e.altKey, ctrl = e.ctrlKey, shift = e.shiftKey;
// Detect escape
if (e.which == 0) {
key = e.keyCode;
}
// console.log("### mel_shortcuts_keydown");
// console.log(e.which);
// console.log(e.keyCode);
// do nothing on input elements if no ctrl
if ($(e.target).is('textarea,input')) {
return true;
}
// do nothing if any popup menu is displayed
if ($('.popupmenu:visible').length) {
return true;
}
for (i in mel_shortcuts_down) {
handler = mel_shortcuts_down[i];
// check if presses key(s) match
if (handler.keydown == key
&& ((handler.ctrl && ctrl) || (!handler.ctrl && !ctrl))
&& ((handler.alt && alt) || (!handler.alt && !alt))
&& ((handler.shift && shift) || (!handler.shift && !shift))
) {
// ... and action is active here
if (handler.active(e)) {
// execute action, the real check if action is active
// will be done in .action() or in rcmail.command()
handler.action(e);
e.preventDefault();
e.stopImmediatePropagation();
return false;
}
// we can break here, there can be only one handler
// for the specified shortcut
break;
}
}
return true;
};
// register the keypress and keydown handler
window.rcmail && $(document).ready(function() {
$(document).on('keypress', function(e) {
return mel_shortcuts_keypress(e);
});
$(document).on('keydown', function(e) {
return mel_shortcuts_keydown(e);
});
});