From 763ed856688d7c4ac32446ef564d602878b44f22 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 29 Mar 2022 09:16:19 -0600 Subject: [PATCH] Fix splitter widget did not restore size from preference Two problems: 1. Preference was stored as percent which splitter did not like to load directly 2. Etemplate was triggering the final finish-up, which triggered resize(), which stored the default as preference before the splitter got to its _init_splitter(), --- api/js/etemplate/et2_widget_split.ts | 19 ++-- api/js/etemplate/etemplate2.ts | 152 ++++++++++++++------------- 2 files changed, 91 insertions(+), 80 deletions(-) diff --git a/api/js/etemplate/et2_widget_split.ts b/api/js/etemplate/et2_widget_split.ts index 565cbf719d..642236e6f5 100644 --- a/api/js/etemplate/et2_widget_split.ts +++ b/api/js/etemplate/et2_widget_split.ts @@ -161,10 +161,12 @@ export class et2_split extends et2_DOMWidget implements et2_IResizeable, et2_IPr super.doLoadingFinished(); // Not done yet, but widget will let you know - return new Promise((resolve) => { + let p = new Promise((resolve) => + { // Use a timeout to give the children a chance to finish - window.setTimeout(() => this._init_splitter(resolve),1); + window.setTimeout(() => this._init_splitter(resolve), 1); }); + return p; } /** @@ -216,12 +218,17 @@ export class et2_split extends et2_DOMWidget implements et2_IResizeable, et2_IPr let pref = this.egw().preference('splitter-size-' + this.id, this.egw().getAppName()); if(pref) { - if(this.orientation == "v" && pref['sizeLeft'] < this.dynheight.outerNode.width() || - this.orientation == "h" && pref['sizeTop'] < this.dynheight.outerNode.height()) + // Change from percent back to numeric + if(typeof pref.sizeLeft !== "undefined") { - options = jQuery.extend(options, pref); - this.prefSize = pref[this.orientation == "v" ?'sizeLeft' : 'sizeTop']; + pref.sizeLeft = ((parseFloat(pref.sizeLeft) / 100) * widget.dynheight.outerNode.width()); } + if(typeof pref.sizeTop !== "undefined") + { + pref.sizeTop = ((parseFloat(pref.sizeTop) / 100) * widget.dynheight.outerNode.height()); + } + options = jQuery.extend(options, pref); + this.prefSize = pref[this.orientation == "v" ? 'sizeLeft' : 'sizeTop']; } // If there is no preference yet, set it to half size // Otherwise the right pane gets the fullsize diff --git a/api/js/etemplate/etemplate2.ts b/api/js/etemplate/etemplate2.ts index 47a0a4f706..090d82d1d3 100644 --- a/api/js/etemplate/etemplate2.ts +++ b/api/js/etemplate/etemplate2.ts @@ -646,93 +646,97 @@ export class etemplate2 egw.window.console.groupEnd(); } - // Wait for everything to be loaded, then finish it up - Promise.all(deferred).then(() => + // Wait for everything to be loaded, then finish it up. Use timeout to give anything else a chance + // to run. + setTimeout(() => { - egw.debug("log", "Finished loading %s, triggering load event", _name); - - if(typeof window.framework != 'undefined' && typeof window.framework.et2_loadingFinished != 'undefined') + Promise.all(deferred).then(() => { - //Call loading finished method of the framework with local window - window.framework.et2_loadingFinished(egw(window).window); - } - // Trigger the "resize" event - this.resize(); + egw.debug("log", "Finished loading %s, triggering load event", _name); - // Automatically set focus to first visible input for popups - if(this._widgetContainer._egw.is_popup() && jQuery('[autofocus]', this._DOMContainer).focus().length == 0) - { - const $input = jQuery('input:visible', this._DOMContainer) - // Date fields open the calendar popup on focus - .not('.et2_date') - .filter(function() + if(typeof window.framework != 'undefined' && typeof window.framework.et2_loadingFinished != 'undefined') + { + //Call loading finished method of the framework with local window + window.framework.et2_loadingFinished(egw(window).window); + } + // Trigger the "resize" event + this.resize(); + + // Automatically set focus to first visible input for popups + if(this._widgetContainer._egw.is_popup() && jQuery('[autofocus]', this._DOMContainer).focus().length == 0) + { + const $input = jQuery('input:visible', this._DOMContainer) + // Date fields open the calendar popup on focus + .not('.et2_date') + .filter(function() + { + // Skip inputs that are out of tab ordering + const $this = jQuery(this); + return !$this.attr('tabindex') || parseInt($this.attr('tabIndex')) >= 0; + }).first(); + + // mobile device, focus only if the field is empty (usually means new entry) + // should focus always for non-mobile one + if(egwIsMobile() && $input.val() == "" || !egwIsMobile()) { - // Skip inputs that are out of tab ordering - const $this = jQuery(this); - return !$this.attr('tabindex') || parseInt($this.attr('tabIndex')) >= 0; - }).first(); - - // mobile device, focus only if the field is empty (usually means new entry) - // should focus always for non-mobile one - if(egwIsMobile() && $input.val() == "" || !egwIsMobile()) - { - $input.focus(); + $input.focus(); + } } - } - // Tell others about it - if(typeof _callback == "function") - { - _callback.call(window, this, _name); - } - if(app_callback && _callback != app_callback && !_no_et2_ready) - { - app_callback.call(window, this, _name); - } - if(appname && appname != this.app && typeof app[this.app] == "object" && !_no_et2_ready) - { - // Loaded a template from a different application? - // Let the application that loaded it know too - app[this.app].et2_ready(this, this.name); - } + // Tell others about it + if(typeof _callback == "function") + { + _callback.call(window, this, _name); + } + if(app_callback && _callback != app_callback && !_no_et2_ready) + { + app_callback.call(window, this, _name); + } + if(appname && appname != this.app && typeof app[this.app] == "object" && !_no_et2_ready) + { + // Loaded a template from a different application? + // Let the application that loaded it know too + app[this.app].et2_ready(this, this.name); + } - // Dispatch an event that will bubble through shadow DOM boundary (pass through custom elements) - this._DOMContainer.dispatchEvent(new CustomEvent('load', { - bubbles: true, - composed: true, - detail: this - })); + // Dispatch an event that will bubble through shadow DOM boundary (pass through custom elements) + this._DOMContainer.dispatchEvent(new CustomEvent('load', { + bubbles: true, + composed: true, + detail: this + })); - if(etemplate2.templates[this.name].attributes.onload) - { - let onload = et2_checkType(etemplate2.templates[this.name].attributes.onload.value, 'js', 'onload', {}); - if(typeof onload === 'string') + if(etemplate2.templates[this.name].attributes.onload) { - onload = et2_compileLegacyJS(onload, this, this._widgetContainer); + let onload = et2_checkType(etemplate2.templates[this.name].attributes.onload.value, 'js', 'onload', {}); + if(typeof onload === 'string') + { + onload = et2_compileLegacyJS(onload, this, this._widgetContainer); + } + onload.call(this._widgetContainer); } - onload.call(this._widgetContainer); - } - // Profiling - if(egw.debug_level() >= 4) - { - if(console.timeEnd) + // Profiling + if(egw.debug_level() >= 4) { - console.timeEnd(_name); + if(console.timeEnd) + { + console.timeEnd(_name); + } + if(console.profileEnd) + { + console.profileEnd(_name); + } + const end_time = (new Date).getTime(); + let gen_time_div = jQuery('#divGenTime_' + appname); + if(!gen_time_div.length) + { + gen_time_div = jQuery('.pageGenTime'); + } + gen_time_div.find('.et2RenderTime').remove(); + gen_time_div.append('' + egw.lang('eT2 rendering took %1s', '' + ((end_time - start_time) / 1000)) + ''); } - if(console.profileEnd) - { - console.profileEnd(_name); - } - const end_time = (new Date).getTime(); - let gen_time_div = jQuery('#divGenTime_' + appname); - if(!gen_time_div.length) - { - gen_time_div = jQuery('.pageGenTime'); - } - gen_time_div.find('.et2RenderTime').remove(); - gen_time_div.append('' + egw.lang('eT2 rendering took %1s', '' + ((end_time - start_time) / 1000)) + ''); - } + }); }); };