diff --git a/src/utils/Resizer.js b/src/utils/Resizer.js index b66aa20f6be..07cf14d8ac6 100644 --- a/src/utils/Resizer.js +++ b/src/utils/Resizer.js @@ -128,8 +128,6 @@ define(function (require, exports, module) { * before collapse. May occur without any resize events. * - panelExpanded: When the panel gets expanded (or shown). Passed the initial size. * May occur without any resize events. - * TODO (#2079): Spurious resize events may occur after collapse or before expand, reporting - * the wrong size. If a panel is currently hidden (display:none), ignore these events. * * @param {!DOMNode} element DOM element which should be made resizable. * @param {!string} direction Direction of the resize action: one of the DIRECTION_* constants. @@ -167,11 +165,24 @@ define(function (require, exports, module) { } } + function resizeElement(elementSize, contentSize) { + elementSizeFunction.apply($element, [elementSize]); + + if ($resizableElement.length) { + contentSizeFunction.apply($resizableElement, [contentSize]); + } + } + $element.data("show", function () { var elementOffset = $element.offset(), - elementSize = elementSizeFunction.apply($element), + elementSize = elementSizeFunction.apply($element) || elementPrefs.size, + contentSize = contentSizeFunction.apply($resizableElement) || elementPrefs.contentSize, resizerSize = elementSizeFunction.apply($resizer); - + + // Resize the element before showing it again. If the panel was collapsed by dragging + // the resizer, the size of the element should be 0, so we restore size in preferences + resizeElement(elementSize, contentSize); + $element.show(); elementPrefs.visible = true; @@ -229,18 +240,18 @@ define(function (require, exports, module) { } $resizer.on("mousedown", function (e) { - var $resizeCont = $("
"), + var $resizeShield = $("
"), startPosition = e[directionProperty], startSize = $element.is(":visible") ? elementSizeFunction.apply($element) : 0, newSize = startSize, + previousSize = startSize, baseSize = 0, - doResize = false, isMouseDown = true, resizeStarted = false; - $body.append($resizeCont); + $body.append($resizeShield); - if ($resizableElement !== undefined) { + if ($resizableElement.length) { $element.children().not(".horz-resizer, .vert-resizer, .resizable-content").each(function (index, child) { if (direction === DIRECTION_HORIZONTAL) { baseSize += $(child).outerWidth(); @@ -250,33 +261,44 @@ define(function (require, exports, module) { }); } - animationRequest = window.webkitRequestAnimationFrame(function doRedraw() { + function doRedraw() { // only run this if the mouse is down so we don't constantly loop even // after we're done resizing. if (!isMouseDown) { return; } - if (doResize) { - // resize the main element to the new size - if ($element.is(":visible")) { - elementSizeFunction.apply($element, [newSize]); - - // if there is a content element, its size is the new size - // minus the size of the non-resizable elements - if ($resizableElement !== undefined) { - contentSizeFunction.apply($resizableElement, [newSize - baseSize]); - } + // Check for real size changes to avoid unnecessary resizing and events + if (newSize !== previousSize) { + previousSize = newSize; + if ($element.is(":visible")) { if (newSize < 10) { toggle($element); + elementSizeFunction.apply($element, [0]); } else { + // Trigger resizeStarted just before the first successful resize update + if (!resizeStarted) { + resizeStarted = true; + $element.trigger("panelResizeStart", newSize); + } + + // Resize the main element to the new size. If there is a content element, + // its size is the new size minus the size of the non-resizable elements + resizeElement(newSize, (newSize - baseSize)); forceMargins(newSize); + + $element.trigger("panelResizeUpdate", [newSize]); } } else if (newSize > 10) { elementSizeFunction.apply($element, [newSize]); toggle($element); - $element.trigger("panelResizeStart", [elementSizeFunction.apply($element)]); + + // Trigger resizeStarted after expanding the element if it was previously collapsed + if (!resizeStarted) { + resizeStarted = true; + $element.trigger("panelResizeStart", newSize); + } } // Vertical resize affects editor directly; horizontal resize could change height of top toolbar @@ -284,60 +306,64 @@ define(function (require, exports, module) { } animationRequest = window.webkitRequestAnimationFrame(doRedraw); - }); + } - $resizeCont.on("mousemove", function (e) { - - // Trigger resizeStarted only if we move the mouse to avoid a resizeStarted event - // when double clicking for collapse/expand functionality - if (!resizeStarted) { - resizeStarted = true; - $element.trigger("panelResizeStart", [elementSizeFunction.apply($element)]); - } - - doResize = true; + function onMouseMove(e) { // calculate newSize adding to startSize the difference // between starting and current position, capped at minSize newSize = Math.max(startSize + directionIncrement * (startPosition - e[directionProperty]), minSize); - $element.trigger("panelResizeUpdate", [newSize]); e.preventDefault(); - }); + + if (animationRequest === null) { + animationRequest = window.webkitRequestAnimationFrame(doRedraw); + } + } + + $(window.document).on("mousemove", onMouseMove); // If the element is marked as collapsible, check for double click // to toggle the element visibility if (collapsible) { - $resizeCont.on("mousedown", function (e) { + $resizeShield.on("mousedown", function (e) { + $(window.document).off("mousemove", onMouseMove); + $resizeShield.off("mousedown"); + $resizeShield.remove(); + animationRequest = null; toggle($element); }); } function endResize(e) { - var elementSize = elementSizeFunction.apply($element); - - elementPrefs.size = elementSize; - - if (contentSizeFunction) { - elementPrefs.contentSize = contentSizeFunction.apply($resizableElement); - } - if (isMouseDown) { + + var elementSize = elementSizeFunction.apply($element); + if ($element.is(":visible")) { + elementPrefs.size = elementSize; + if ($resizableElement.length) { + elementPrefs.contentSize = contentSizeFunction.apply($resizableElement); + } + _prefs.setValue(elementID, elementPrefs); + repositionResizer(elementSize); + } + isMouseDown = false; - repositionResizer(elementSize); - $element.trigger("panelResizeEnd", [elementSize]); - _prefs.setValue(elementID, elementPrefs); - // We wait 100ms to remove the resizer container to capture a mousedown + if (resizeStarted) { + $element.trigger("panelResizeEnd", [elementSize]); + } + + // We wait 300ms to remove the resizer container to capture a mousedown // on the container that would account for double click window.setTimeout(function () { - $resizeCont.off("mousemove"); - $resizeCont.off("mousedown"); - $resizeCont.remove(); - }, 100); + $(window.document).off("mousemove", onMouseMove); + $resizeShield.off("mousedown"); + $resizeShield.remove(); + animationRequest = null; + }, 300); } } - $resizeCont.one("mouseup", endResize); - $resizeCont.mouseleave(endResize); + $(window.document).one("mouseup", endResize); e.preventDefault(); }); @@ -346,11 +372,11 @@ define(function (require, exports, module) { if (elementPrefs) { if (elementPrefs.size !== undefined) { - elementSizeFunction.apply($element, [Math.max(elementPrefs.size, minSize)]); + elementSizeFunction.apply($element, [elementPrefs.size]); } if (elementPrefs.contentSize !== undefined) { - contentSizeFunction.apply($resizableElement, [Math.max(elementPrefs.contentSize, minSize)]); + contentSizeFunction.apply($resizableElement, [elementPrefs.contentSize]); } if (elementPrefs.visible !== undefined && !elementPrefs.visible) {