Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Resize events consolidation and minor resizer bugs (#2079) #2092

Merged
merged 4 commits into from
Nov 21, 2012
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 80 additions & 54 deletions src/utils/Resizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -229,18 +240,18 @@ define(function (require, exports, module) {
}

$resizer.on("mousedown", function (e) {
var $resizeCont = $("<div class='resizing-container " + direction + "-resizing' />"),
var $resizeShield = $("<div class='resizing-container " + direction + "-resizing' />"),
startPosition = e[directionProperty],
startSize = $element.is(":visible") ? elementSizeFunction.apply($element) : 0,
newSize = startSize,
previousSize = startSize,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think of it, currentSize may be a better name for this...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think previousSize is an ok enough name.

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();
Expand All @@ -250,94 +261,109 @@ 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
EditorManager.resizeEditor();
}

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();
});
Expand All @@ -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]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason you removed the checks for minSize?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, yeah... I forgot to comment on that. The previous logic was wrong and somehow misleading and I wanted to check with you the best approach to take here.

Now that the panels have min-size, the only way for minSize to be chosen here is if we change the minimum size for the panel to a bigger value than the one stored in the preferences in the previous session. With that in mind, we can do two things:

  1. Don't check for minSize. This shows the panel with the stored sizes and the moment you start resizing it jumps to the new minimum size directly.
  2. Check for minSize (like previously), which should automatically resize the panel to the minSize.

There were a couple of issues with 2 before:

  • If you resize the panel to the minimum size (in which case size==minSize), contentSize is always smaller than minSize and we are forcing always a bigger size on it (the scrollbars aren't quite right).
  • If you raise minSize, the panel is resized correctly, but again the content isn't and it is always getting resized to minSize. We'd probably need to set it to minSize-(size-contentSize).
  • We may want to save the preferences in this case, although the code won't complain.

Which behavior do you prefer? If it's the second, I could push it along with the rest of review changes or fix it in a separate issue (I'd say that without the checks, the code at least behaves is it says it does)

}

if (elementPrefs.visible !== undefined && !elementPrefs.visible) {
Expand Down