Use Left/Right Arrow keys to faster move over threaded messages list (#6399)

Fixed some inconsistencies in list widget expand/collapse code.

Made the arrow keys behavior like in Thunderbird, i.e.:
- Right Arrow expands thread or selects closest child if already expanded,
- Left Arrow collapses thread or jumps to closest parent,
- Left Arrow + Ctrl selects top-most parent,
- Up/Down Arrow keys behavior didn't change.
pull/6894/head
Aleksander Machniak 5 years ago
parent dc5be05a5f
commit 9a225bd3fe

@ -14,6 +14,7 @@ CHANGELOG Roundcube Webmail
- Added 'keyservers' option to define list of HKP servers for Enigma/Mailvelope (#6326) - Added 'keyservers' option to define list of HKP servers for Enigma/Mailvelope (#6326)
- Added flag to disable server certificate validation via Mysql DSN argument (#6848) - Added flag to disable server certificate validation via Mysql DSN argument (#6848)
- Select all records on the current list page with CTRL + A (#6813) - Select all records on the current list page with CTRL + A (#6813)
- Use Left/Right Arrow keys to faster move over threaded messages list (#6399)
- Changes in `display_next` setting (#6795): - Changes in `display_next` setting (#6795):
- Move it to Preferences > User Interface > Main Options - Move it to Preferences > User Interface > Main Options
- Make it apply to Contacts interface too - Make it apply to Contacts interface too

@ -732,25 +732,13 @@ expand_row: function(e, id)
{ {
var row = this.rows[id], var row = this.rows[id],
evtarget = rcube_event.get_target(e), evtarget = rcube_event.get_target(e),
mod_key = rcube_event.get_modifier(e); mod_key = rcube_event.get_modifier(e),
action = (row.expanded ? 'collapse' : 'expand') + (mod_key == CONTROL_KEY || this.multiexpand ? '_all' : '');
// Don't treat double click on the expando as double click on the message. // Don't treat double click on the expando as double click on the message.
row.clicked = 0; row.clicked = 0;
if (row.expanded) { this[action](row);
evtarget.className = 'collapsed';
if (mod_key == CONTROL_KEY || this.multiexpand)
this.collapse_all(row);
else
this.collapse(row);
}
else {
evtarget.className = 'expanded';
if (mod_key == CONTROL_KEY || this.multiexpand)
this.expand_all(row);
else
this.expand(row);
}
}, },
collapse: function(row) collapse: function(row)
@ -759,6 +747,7 @@ collapse: function(row)
new_row = row ? row.obj.nextSibling : null; new_row = row ? row.obj.nextSibling : null;
row.expanded = false; row.expanded = false;
this.update_expando(row.id);
this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj }); this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj });
while (new_row) { while (new_row) {
@ -814,6 +803,7 @@ expand: function(row)
last_expanded_parent_depth = p.depth; last_expanded_parent_depth = p.depth;
$(new_row).css('display', ''); $(new_row).css('display', '');
r.expanded = true; r.expanded = true;
this.update_expando(r.id, true);
this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded, obj:new_row }); this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded, obj:new_row });
} }
} }
@ -828,6 +818,7 @@ expand: function(row)
this.resize(); this.resize();
this.triggerEvent('listupdate'); this.triggerEvent('listupdate');
return false; return false;
}, },
@ -843,7 +834,7 @@ collapse_all: function(row)
this.update_expando(row.id); this.update_expando(row.id);
this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj }); this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj });
// don't collapse sub-root tree in multiexpand mode // don't collapse sub-root tree in multiexpand mode
if (depth && this.multiexpand) if (depth && this.multiexpand)
return false; return false;
} }
@ -860,10 +851,12 @@ collapse_all: function(row)
if (row || r.depth) if (row || r.depth)
$(new_row).css('display', 'none'); $(new_row).css('display', 'none');
if (r.has_children && r.expanded) { if (r.expanded) {
r.expanded = false; r.expanded = false;
this.update_expando(r.id, false); if (r.has_children) {
this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded, obj:new_row }); this.update_expando(r.id);
this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded, obj:new_row });
}
} }
} }
} }
@ -872,6 +865,7 @@ collapse_all: function(row)
this.resize(); this.resize();
this.triggerEvent('listupdate'); this.triggerEvent('listupdate');
return false; return false;
}, },
@ -899,10 +893,12 @@ expand_all: function(row)
break; break;
$(new_row).css('display', ''); $(new_row).css('display', '');
if (r.has_children && !r.expanded) { if (!r.expanded) {
r.expanded = true; r.expanded = true;
this.update_expando(r.id, true); if (r.has_children) {
this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded, obj:new_row }); this.update_expando(r.id, true);
this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded, obj:new_row });
}
} }
} }
} }
@ -911,6 +907,7 @@ expand_all: function(row)
this.resize(); this.resize();
this.triggerEvent('listupdate'); this.triggerEvent('listupdate');
return false; return false;
}, },
@ -1429,29 +1426,20 @@ key_press: function(e)
mod_key = rcube_event.get_modifier(e); mod_key = rcube_event.get_modifier(e);
switch (keyCode) { switch (keyCode) {
case 40: case 37: // Left arrow
case 38: case 39: // Right arrow
case 63233: // "down", in safari keypress case 40: // Up arrow
case 63232: // "up", in safari keypress case 38: // Down arrow
case 63233: // "down" in Safari keypress
case 63232: // "up" in Safari keypress
// Stop propagation so that the browser doesn't scroll // Stop propagation so that the browser doesn't scroll
rcube_event.cancel(e); rcube_event.cancel(e);
return this.use_arrow_key(keyCode, mod_key); return this.use_arrow_key(keyCode, mod_key);
case 32: case 32: // Space
rcube_event.cancel(e); rcube_event.cancel(e);
return this.select_row(this.last_selected, mod_key, true); return this.select_row(this.last_selected, mod_key, true);
case 37: // Left arrow
case 39: // Right arrow
// Stop propagation
rcube_event.cancel(e);
var ret = this.use_arrow_key(keyCode, mod_key);
this.key_pressed = keyCode;
this.modkey = mod_key;
this.triggerEvent('keypress');
this.modkey = 0;
return ret;
case 36: // Home case 36: // Home
this.select_first(mod_key); this.select_first(mod_key);
return rcube_event.cancel(e); return rcube_event.cancel(e);
@ -1506,43 +1494,39 @@ key_press: function(e)
*/ */
use_arrow_key: function(keyCode, mod_key) use_arrow_key: function(keyCode, mod_key)
{ {
var new_row, var new_row, selected_row = this.rows[this.last_selected];
selected_row = this.rows[this.last_selected];
// Safari uses the nonstandard keycodes 63232/63233 for up/down, if we're if (!selected_row) {
// select the first row if none selected yet
this.select_first(CONTROL_KEY);
}
// Safari uses the non-standard keycodes 63232/63233 for up/down, if we're
// using the keypress event (but not the keydown or keyup event). // using the keypress event (but not the keydown or keyup event).
if (keyCode == 40 || keyCode == 63233) // down arrow key pressed else if (keyCode == 40 || keyCode == 63233) // Down arrow
new_row = this.get_next_row(); new_row = this.get_next_row();
else if (keyCode == 38 || keyCode == 63232) // up arrow key pressed else if (keyCode == 38 || keyCode == 63232) // Up arrow
new_row = this.get_prev_row(); new_row = this.get_prev_row();
else { else if (keyCode == 39 && selected_row.has_children) { // Right arrow
if (!selected_row || !selected_row.has_children) if (!selected_row.expanded)
return; this.expand_all(selected_row);
// expand
if (keyCode == 39) {
if (selected_row.expanded)
return;
if (mod_key == CONTROL_KEY || this.multiexpand)
this.expand_all(selected_row);
else
this.expand(selected_row);
}
// collapse
else { else {
if (!selected_row.expanded) // jump to the first child
return; new_row = this.get_next_row();
mod_key = null;
if (mod_key == CONTROL_KEY || this.multiexpand)
this.collapse_all(selected_row);
else
this.collapse(selected_row);
} }
}
else if (keyCode == 37) { // Left arrow
if (selected_row.expanded && selected_row.has_children && (!selected_row.parent_uid || !this.multiexpand))
this.collapse_all(selected_row);
else if (selected_row.parent_uid) {
// jump to the top-most or closest parent
if (mod_key == CONTROL_KEY)
new_row = this.rows[this.find_root(selected_row.uid)];
else
new_row = this.rows[selected_row.parent_uid];
this.update_expando(selected_row.id, selected_row.expanded); mod_key = null;
}
return false;
} }
if (new_row) { if (new_row) {
@ -1553,10 +1537,6 @@ use_arrow_key: function(keyCode, mod_key)
this.select_row(new_row.uid, mod_key, false); this.select_row(new_row.uid, mod_key, false);
this.scrollto(new_row.uid); this.scrollto(new_row.uid);
} }
else if (!new_row && !selected_row) {
// select the first row if none selected yet
this.select_first(CONTROL_KEY);
}
return false; return false;
}, },

Loading…
Cancel
Save