[MediaWiki-commits] [Gerrit] Window: Avoid height flickering when resizing dialogs - change (oojs/ui)
jenkins-bot has submitted this change and it was merged. Change subject: Window: Avoid height flickering when resizing dialogs .. Window: Avoid height flickering when resizing dialogs When you have a dialog open and resize the browser window, the dialog will appear to close and re-open (even if its size has not actually changed). This is because CSS transitions suck. * Factor out a Window#withoutSizeTransitions helper function from Window#getContentHeight, which disables resize transitions on the given window, runs some code and enables the transitions back. * Correct the code in Window#setDimensions which aimed to calculate the necessary window height after setting its width, but failed to do so because it didn't account for the transition on the width. Bug: T76371 Change-Id: I410f42949b81f439ab712a263498ba6012de2e23 --- M src/Window.js 1 file changed, 48 insertions(+), 13 deletions(-) Approvals: Trevor Parscal: Looks good to me, approved jenkins-bot: Verified diff --git a/src/Window.js b/src/Window.js index 7a16e87..e2d066d 100644 --- a/src/Window.js +++ b/src/Window.js @@ -303,25 +303,46 @@ }; /** - * Get the height of the dialog contents. + * Disable transitions on window's frame for the duration of the callback function, then enable them + * back. * - * @return {number} Content height + * @private + * @param {Function} callback Function to call while transitions are disabled */ -OO.ui.Window.prototype.getContentHeight = function () { +OO.ui.Window.prototype.withoutSizeTransitions = function ( callback ) { // Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements. // Disable transitions first, otherwise we'll get values from when the window was animating. - var bodyHeight, oldHeight, oldTransition, + var oldTransition, styleObj = this.$frame[0].style; oldTransition = styleObj.transition || styleObj.OTransition || styleObj.MsTransition || styleObj.MozTransition || styleObj.WebkitTransition; styleObj.transition = styleObj.OTransition = styleObj.MsTransition = styleObj.MozTransition = styleObj.WebkitTransition = 'none'; - oldHeight = styleObj.height; - styleObj.height = '1px'; - bodyHeight = this.getBodyHeight(); - styleObj.height = oldHeight; + callback(); + // Force reflow to make sure the style changes done inside callback really are not transitioned + this.$frame.height(); styleObj.transition = styleObj.OTransition = styleObj.MsTransition = styleObj.MozTransition = styleObj.WebkitTransition = oldTransition; +}; + +/** + * Get the height of the dialog contents. + * + * @return {number} Content height + */ +OO.ui.Window.prototype.getContentHeight = function () { + var bodyHeight, + win = this, + styleObj = this.$frame[0].style; + + // Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements. + // Disable transitions first, otherwise we'll get values from when the window was animating. + this.withoutSizeTransitions( function () { + var oldHeight = styleObj.height; + styleObj.height = '1px'; + bodyHeight = win.getBodyHeight(); + styleObj.height = oldHeight; + } ); return Math.round( // Add buffer for border @@ -517,17 +538,31 @@ * @chainable */ OO.ui.Window.prototype.setDimensions = function ( dim ) { - // Apply width before height so height is not based on wrapping content using the wrong width + var height, + win = this, + styleObj = this.$frame[0].style; + + // Calculate the height we need to set using the correct width + if ( dim.height === undefined ) { + this.withoutSizeTransitions( function () { + var oldWidth = styleObj.width; + win.$frame.css( 'width', dim.width || '' ); + height = win.getContentHeight(); + styleObj.width = oldWidth; + } ); + } else { + height = dim.height; + } + this.$frame.css( { width: dim.width || '', minWidth: dim.minWidth || '', - maxWidth: dim.maxWidth || '' - } ); - this.$frame.css( { - height: ( dim.height !== undefined ? dim.height : this.getContentHeight() ) || '', + maxWidth: dim.maxWidth || '', + height: height || '', minHeight: dim.minHeight || '', maxHeight: dim.maxHeight || '' } ); + return this; }; -- To view, visit https://gerrit.wikimedia.org/r/176484 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id:
[MediaWiki-commits] [Gerrit] Window: Avoid height flickering when resizing dialogs - change (oojs/ui)
Bartosz DziewoĆski has uploaded a new change for review. https://gerrit.wikimedia.org/r/176484 Change subject: Window: Avoid height flickering when resizing dialogs .. Window: Avoid height flickering when resizing dialogs When you have a dialog open and resize the browser window, the dialog will appear to close and re-open (even if its size has not actually changed). This is because CSS transitions suck. * Factor out a Window#withoutSizeTransitions helper function from Window#getContentHeight, which disables resize transitions on the given window, runs some code and enables the transitions back. * Correct the code in Window#setDimensions which aimed to calculate the necessary window height after setting its width, but failed to do so because it didn't account for the transition on the width. Change-Id: I410f42949b81f439ab712a263498ba6012de2e23 --- M src/Window.js 1 file changed, 49 insertions(+), 13 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/84/176484/1 diff --git a/src/Window.js b/src/Window.js index 7a16e87..4d7c597 100644 --- a/src/Window.js +++ b/src/Window.js @@ -303,25 +303,47 @@ }; /** - * Get the height of the dialog contents. + * Disable transitions on window's frame for the duration of the callback function, then enable them + * back. * - * @return {number} Content height + * @private + * @param {Function} callback Function to call while transitions are disabled */ -OO.ui.Window.prototype.getContentHeight = function () { +OO.ui.Window.prototype.withoutSizeTransitions = function ( callback ) { // Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements. // Disable transitions first, otherwise we'll get values from when the window was animating. - var bodyHeight, oldHeight, oldTransition, + var oldTransition, styleObj = this.$frame[0].style; oldTransition = styleObj.transition || styleObj.OTransition || styleObj.MsTransition || styleObj.MozTransition || styleObj.WebkitTransition; styleObj.transition = styleObj.OTransition = styleObj.MsTransition = styleObj.MozTransition = styleObj.WebkitTransition = 'none'; - oldHeight = styleObj.height; - styleObj.height = '1px'; - bodyHeight = this.getBodyHeight(); - styleObj.height = oldHeight; + callback(); + // Force reflow to make sure the style changes done inside callback really are not transitioned + this.$frame.height(); styleObj.transition = styleObj.OTransition = styleObj.MsTransition = styleObj.MozTransition = styleObj.WebkitTransition = oldTransition; +}; + + +/** + * Get the height of the dialog contents. + * + * @return {number} Content height + */ +OO.ui.Window.prototype.getContentHeight = function () { + var bodyHeight, + window = this, + styleObj = this.$frame[0].style; + + // Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements. + // Disable transitions first, otherwise we'll get values from when the window was animating. + this.withoutSizeTransitions( function () { + var oldHeight = styleObj.height; + styleObj.height = '1px'; + bodyHeight = window.getBodyHeight(); + styleObj.height = oldHeight; + } ); return Math.round( // Add buffer for border @@ -517,17 +539,31 @@ * @chainable */ OO.ui.Window.prototype.setDimensions = function ( dim ) { - // Apply width before height so height is not based on wrapping content using the wrong width + var height, + window = this, + styleObj = this.$frame[0].style; + + // Calculate the height we need to set using the correct width + if ( dim.height === undefined ) { + this.withoutSizeTransitions( function () { + var oldWidth = styleObj.width; + window.$frame.css( 'width', dim.width || '' ); + height = window.getContentHeight(); + styleObj.width = oldWidth; + } ); + } else { + height = dim.height; + } + this.$frame.css( { width: dim.width || '', minWidth: dim.minWidth || '', - maxWidth: dim.maxWidth || '' - } ); - this.$frame.css( { - height: ( dim.height !== undefined ? dim.height : this.getContentHeight() ) || '', + maxWidth: dim.maxWidth || '', + height: height || '', minHeight: dim.minHeight || '', maxHeight: dim.maxHeight || '' } ); + return this; }; -- To view, visit https://gerrit.wikimedia.org/r/176484 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings