From 58ffbe2a83bc88edeccf238a0b8084e18b10f42f Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sat, 1 Dec 2018 17:40:58 +0100 Subject: [PATCH] Elastic: Datepicker improvements - Added real background overlay, to fix issues with clicking outside of the datepicker element - Use better positioning technique - Re-styling on calendar update --- skins/elastic/styles/widgets/jqueryui.less | 25 +++++++------- skins/elastic/ui.js | 40 ++++++++++++++++++---- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/skins/elastic/styles/widgets/jqueryui.less b/skins/elastic/styles/widgets/jqueryui.less index 022c629d8..1a71fb7f5 100644 --- a/skins/elastic/styles/widgets/jqueryui.less +++ b/skins/elastic/styles/widgets/jqueryui.less @@ -14,6 +14,7 @@ .ui-widget-overlay { background-color: @color-dialog-overlay-background; opacity: 1 !important; // override jQuery-UI opacity, the color above is semi-transparent + z-index: 10; // above Bootstrap's form controls } .ui-widget { @@ -286,11 +287,10 @@ .ui-datepicker { // Always display datepicker centered, overwriting widgets position - position: fixed !important; - top: 50% !important; - left: 50% !important; - transform: translate(-50%, -50%); - box-shadow: 10px 10px 10px 1000px @color-dialog-overlay-background; + margin: ~"calc(50vh - 13em) calc(50vw - 10em) !important"; + top: 0 !important; + left: 0 !important; + box-shadow: none; &:not(.ui-datepicker-inline) { z-index: 120 !important; // fixes datepicker over input-group and dialogs @@ -314,6 +314,7 @@ display: inline-block; } } + .ui-icon { background-image: none !important; background-position: none !important; @@ -366,15 +367,13 @@ color: @color-datepicker-active; font-weight: bold; } -} -html.touch { - .ui-datepicker { - min-width: (@screen-width-mini - 20px); - - td a { - font-size: 1.2em; - line-height: 2.2em; + html.touch { + & { + td a { + font-size: 1.2em; + line-height: 2.2em; + } } } } diff --git a/skins/elastic/ui.js b/skins/elastic/ui.js index 61f97d662..dd437b79a 100644 --- a/skins/elastic/ui.js +++ b/skins/elastic/ui.js @@ -733,6 +733,39 @@ function rcube_elastic_ui() $('input.datepicker').each(function() { func(this); }); rcmail.addEventListener('insert-edit-field', func); } + + // Datepicker widget improvements: overlay element, styling updates on calendar element update + // The widget does not provide any event system, so we use MutationObserver + if (window.MutationObserver) { + var overlay, hidden = true, + callback = function(data) { + $.each(data, function(i, v) { + // add/remove overlay on widget show/hide + if (v.type == 'attributes') { + var is_hidden = $(v.target).attr('aria-hidden') == 'true'; + if (is_hidden != hidden) { + if (!is_hidden) { + overlay = $('
').attr('class', 'ui-widget-overlay') + .appendTo('body') + .click(function(e) { $(this).remove(); }); + } + else if (overlay) { + overlay.remove(); + } + hidden = is_hidden; + } + } + // apply styles if widget content changed + else if (v.addedNodes.length) { + bootstrap_style(v.target); + } + }); + }; + + $('.ui-datepicker').each(function() { + (new MutationObserver(callback)).observe(this, {childList: true, subtree: false, attributes: true, attributeFilter: ['aria-hidden']}); + }); + } }; /** @@ -987,11 +1020,6 @@ function rcube_elastic_ui() $('a', this).addClass('btn btn-primary'); }); - // Style calendar widget (we use setTimeout() because there's no widget event we could bind to) - $('input.datepicker', context).focus(function() { - setTimeout(function() { bootstrap_style($('.ui-datepicker')); }, 5); - }); - // Form validation errors (managesieve plugin) $('.error', context).addClass('is-invalid'); @@ -3329,7 +3357,7 @@ function rcube_elastic_ui() .append(items) .on('click', 'a.active', function() { // first close the list, then update the select, the order is important - //for cases when the select might be removed in change event (datepicker) + // for cases when the select might be removed in change event (datepicker) var val = $(this).data('value'), ret = close_func(); select.val(val).change(); return ret;