Elastic: Resizeable columns (#6929)

pull/6950/head
Aleksander Machniak 5 years ago
parent 2d9b318c82
commit 4d7ce46fc0

@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Elastic: Resizeable columns (#6929)
RELEASE 1.4-rc2 RELEASE 1.4-rc2
--------------- ---------------
- Update to jQuery 3.4.1 - Update to jQuery 3.4.1

@ -120,6 +120,7 @@ body {
} }
#layout-sidebar { #layout-sidebar {
position: relative; // e.g. for .column-resizer
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 2; flex: 2;
@ -139,6 +140,7 @@ body {
} }
#layout-list { #layout-list {
position: relative; // e.g. for .column-resizer
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 3; flex: 3;
@ -152,7 +154,6 @@ body {
display: flex; display: flex;
flex: 6; flex: 6;
flex-direction: column; flex-direction: column;
min-width: 50%;
background-color: @color-layout-content-background; background-color: @color-layout-content-background;
html.iframe & { html.iframe & {
@ -241,6 +242,20 @@ body {
} }
} }
.column-resizer {
cursor: col-resize;
z-index: 1;
position: absolute;
top: 0;
right: -3px;
width: 6px;
height: 100%;
.sidebar-right & {
left: -3px;
}
}
@media screen and (max-width: @screen-width-large) { @media screen and (max-width: @screen-width-large) {
#layout-sidebar, #layout-sidebar,
@ -256,6 +271,14 @@ body {
} }
@media screen and (max-width: @screen-width-medium) { @media screen and (max-width: @screen-width-medium) {
// Disable column resizing by hiding splitters and reseting columns width
.column-resizer {
display: none;
}
#layout-sidebar,
#layout-list {
width: auto !important;
}
} }
@media screen and (max-width: @screen-width-small) { @media screen and (max-width: @screen-width-small) {

@ -15,7 +15,7 @@
function rcube_elastic_ui() function rcube_elastic_ui()
{ {
var ref = this, var prefs, ref = this,
mode = 'normal', // one of: large, normal, small, phone mode = 'normal', // one of: large, normal, small, phone
touch = false, touch = false,
ios = false, ios = false,
@ -491,6 +491,15 @@ function rcube_elastic_ui()
(new MutationObserver(callback)).observe(document.body, {childList: true}); (new MutationObserver(callback)).observe(document.body, {childList: true});
} }
// Initialize column resizers
if (layout.sidebar.length) {
splitter_init(layout.sidebar);
}
if (layout.list.length) {
splitter_init(layout.list);
}
}; };
/** /**
@ -1707,7 +1716,7 @@ function rcube_elastic_ui()
app_menu(true); app_menu(true);
screen_resize_small_none(); screen_resize_small_none();
if (layout.list) { if (layout.list.length) {
$('.header > ul.menu', layout.list).addClass('popupmenu'); $('.header > ul.menu', layout.list).addClass('popupmenu');
} }
}; };
@ -3870,6 +3879,75 @@ function rcube_elastic_ui()
} }
}; };
/**
* Create a splitter (resizing) element on a layout column
*/
function splitter_init(node)
{
var key = rcmail.env.task + rcmail.env.action + '.' + node.attr('id'),
pos = get_pref(key),
reverted = node.is('.sidebar-right'),
set_width = function(width) {
node.css({
width: Math.max(100, width),
// reset default properties
// 'min-width': 100,
flex: 'none'
});
};
if (!node[reverted ? 'prev' : 'next']().length) {
return;
}
$('<div class="column-resizer">')
.appendTo(node)
.on('mousedown', function(e) {
var ts, splitter = $(this), offset = node.position().left;
// Makes col-resize cursor follow the mouse pointer on dragging
// and fixes issues related to iframes
splitter.width(10000).css(reverted ? 'left' : 'right', -5000);
// Disable selection on document while dragging
// It can happen when you move mouse out of window, on top
document.body.style.userSelect = 'none';
// Start listening to mousemove events
$(document)
.on('mousemove.resizer', function(e) {
// Use of timeouts makes the move more smooth in Chrome
clearTimeout(ts);
ts = setTimeout(function() {
// For left-side-splitter we need the current offset
if (reverted) {
offset = node.position().left;
}
var cursor_position = rcube_event.get_mouse_pos(e).x,
width = reverted ? node.width() + (offset - cursor_position) : cursor_position - offset;
set_width(width);
}, 5);
})
.on('mouseup.resizer', function() {
// Remove registered events
$(document).off('.resizer');
$('iframe').off('.resizer');
document.body.style.userSelect = 'auto';
// Set back the splitter width to normal
splitter.width(6).css(reverted ? 'left' : 'right', -3);
// Save the current position (width)
save_pref(key, node.width());
});
});
if (pos) {
set_width(pos);
}
};
/** /**
* Wrapper for rcmail.open_window to intercept window opening * Wrapper for rcmail.open_window to intercept window opening
* and display a dialog with an iframe instead of a real window. * and display a dialog with an iframe instead of a real window.
@ -3939,6 +4017,47 @@ function rcube_elastic_ui()
return meta.touch; return meta.touch;
}; };
/**
* Get preference stored in browser
*/
function get_pref(key)
{
if (!prefs) {
prefs = rcmail.local_storage_get_item('prefs.elastic', {});
}
// fall-back to cookies
if (prefs[key] == null) {
var cookie = rcmail.get_cookie(key);
if (cookie != null) {
prefs[key] = cookie;
// copy value to local storage and remove cookie (if localStorage is supported)
if (rcmail.local_storage_set_item('prefs.elastic', prefs)) {
rcmail.set_cookie(key, cookie, new Date()); // expire cookie
}
}
}
return prefs[key];
};
/**
* Saves preference value to browser storage
*/
function save_pref(key, val)
{
prefs[key] = val;
// write prefs to local storage (if supported)
if (!rcmail.local_storage_set_item('prefs.elastic', prefs)) {
// store value in cookie
var exp = new Date();
exp.setYear(exp.getFullYear() + 1);
rcmail.set_cookie(key, val, exp);
}
};
} }
if (window.rcmail) { if (window.rcmail) {

Loading…
Cancel
Save