-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New Resizer APIs: show, hide and toggle #1838
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ | |
*/ | ||
|
||
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */ | ||
/*global define, $, window */ | ||
/*global define, $, window, setTimeout */ | ||
|
||
/** | ||
* Resizer is a Module utility to inject resizing capabilities to any element | ||
|
@@ -40,8 +40,10 @@ | |
* while resizing), custom or internal resizes and save the final resized value into local | ||
* storage for example. | ||
* | ||
* TODO Trigger panelResizeStart and panelResizeUpdate as required. They aren't needed | ||
* currently. | ||
* A resizable element can be collapsed/expanded using the `show`, `hide` and `toggle` APIs | ||
* | ||
* The resizable elements trigger a panelCollapsed and panelExpanded event when the panel toggles | ||
* between visible and invisible | ||
*/ | ||
define(function (require, exports, module) { | ||
"use strict"; | ||
|
@@ -63,6 +65,41 @@ define(function (require, exports, module) { | |
|
||
var $mainView; | ||
|
||
/** | ||
* Shows a resizable element. | ||
* @param {DOMNode} element Html element to show if possible | ||
*/ | ||
function show(element) { | ||
var showFunc = $(element).data("show"); | ||
if (showFunc) { | ||
showFunc.apply(element); | ||
} | ||
} | ||
|
||
/** | ||
* Hides a resizable element. | ||
* @param {DOMNode} element Html element to hide if possible | ||
*/ | ||
function hide(element) { | ||
var hideFunc = $(element).data("hide"); | ||
if (hideFunc) { | ||
hideFunc.apply(element); | ||
} | ||
} | ||
|
||
/** | ||
* Changes the visibility state of a resizable element. The toggle | ||
* functionality is added when an element is made resizable. | ||
* @param {DOMNode} element Html element to toggle | ||
*/ | ||
function toggle(element) { | ||
if ($(element).is(":visible")) { | ||
hide(element); | ||
} else { | ||
show(element); | ||
} | ||
} | ||
|
||
/** | ||
* Adds resizing capabilities to a given html element. | ||
* | ||
|
@@ -75,15 +112,21 @@ define(function (require, exports, module) { | |
* - Left ("left") or right ("right") for horizontal resizing | ||
* | ||
* A resizable element triggers the following events while resizing: | ||
* - panelResizeStarts: When the resize starts | ||
* - panelResizeUpdate: When the resize gets updated | ||
* - panelResizeEnds: When the resize ends | ||
* - panelCollapsed: When the panel gets collapsed (or hidden) | ||
* - panelExpanded: When the panel gets expanded (or shown) | ||
* | ||
* @param {DOMNode} element Html element which should be made resizable. | ||
* @param {string} direction The direction of the resize action. Must be "horz" or "vert". | ||
* @param {string} position The position of the resizer on the element. Can be "top" or "bottom" | ||
* for vertical resizing and "left" or "right" for horizontal resizing. | ||
* @param {int} minSize Minimum size (width or height) of the element. | ||
* @param {boolean} collapsable True indicates the panel is collapsable on double click | ||
* on the resizer. | ||
*/ | ||
function makeResizable(element, direction, position, minSize) { | ||
function makeResizable(element, direction, position, minSize, collapsable) { | ||
|
||
var $resizer = $('<div class="' + direction + '-resizer"></div>'), | ||
$element = $(element), | ||
|
@@ -92,23 +135,53 @@ define(function (require, exports, module) { | |
animationRequest = null, | ||
directionProperty = direction === DIRECTION_HORIZONTAL ? "clientX" : "clientY", | ||
elementSizeFunction = direction === DIRECTION_HORIZONTAL ? $element.width : $element.height, | ||
resizerCSSPosition = direction === DIRECTION_HORIZONTAL ? "left" : "top", | ||
contentSizeFunction = null; | ||
|
||
minSize = minSize || 0; | ||
collapsable = collapsable || false; | ||
|
||
$element.prepend($resizer); | ||
|
||
$element.data("show", function () { | ||
$element.show(); | ||
|
||
if (collapsable) { | ||
$element.prepend($resizer); | ||
$resizer.css(resizerCSSPosition, ""); | ||
} | ||
|
||
EditorManager.resizeEditor(); | ||
$element.trigger("panelExpanded"); | ||
$element.trigger("panelResizeEnd", [elementSizeFunction.apply($element)]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this trigger the "panelResizeEnd" event if user only toggled panel display to ON? I would only expect this event after a drag/resize. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think I dragged that from the other branch where I was trying to reuse some code and not in the best possible way, might I add :) I'll remove the panelResizeEnd trigger. |
||
}); | ||
|
||
$element.data("hide", function () { | ||
var elementOffset = $element.offset(), | ||
elementSize = elementSizeFunction.apply($element); | ||
|
||
$element.hide(); | ||
if (collapsable) { | ||
$resizer.insertBefore($element).css(resizerCSSPosition, elementOffset[resizerCSSPosition] + elementSize); | ||
} | ||
|
||
EditorManager.resizeEditor(); | ||
$element.trigger("panelCollapsed"); | ||
}); | ||
|
||
$resizer.on("mousedown", function (e) { | ||
var $resizeCont = $("<div class='resizing-container " + direction + "-resizing' />"), | ||
startPosition = e[directionProperty], | ||
startSize = elementSizeFunction.apply($element), | ||
startSize = $element.is(":visible") ? elementSizeFunction.apply($element) : 0, | ||
newSize = startSize, | ||
baseSize = 0, | ||
doResize = true, | ||
doResize = false, | ||
isMouseDown = true; | ||
|
||
$body.append($resizeCont); | ||
|
||
|
||
$element.trigger("panelResizeStart", [elementSizeFunction.apply($element)]); | ||
|
||
if ($resizableElement !== undefined) { | ||
$element.children().not(".horz-resizer, .vert-resizer, .resizable-content").each(function (index, child) { | ||
if (direction === DIRECTION_HORIZONTAL) { | ||
|
@@ -130,33 +203,59 @@ define(function (require, exports, module) { | |
|
||
if (doResize) { | ||
// resize the main element to the new size | ||
elementSizeFunction.apply($element, [newSize]); | ||
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]); | ||
} | ||
|
||
// 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]); | ||
if (newSize < 10) { | ||
toggle($element); | ||
} | ||
} else if (newSize > 10) { | ||
elementSizeFunction.apply($element, [newSize]); | ||
toggle($element); | ||
$element.trigger("panelResizeStart", [elementSizeFunction.apply($element)]); | ||
} | ||
|
||
EditorManager.resizeEditor(); | ||
} | ||
|
||
animationRequest = window.webkitRequestAnimationFrame(doRedraw); | ||
}); | ||
|
||
$resizeCont.on("mousemove", function (e) { | ||
doResize = true; | ||
// calculate newSize adding to startSize the difference | ||
// between starting and current position, capped at minSize | ||
newSize = Math.max(startSize + (startPosition - e[directionProperty]), minSize); | ||
$element.trigger("panelResizeUpdate", [newSize]); | ||
e.preventDefault(); | ||
}); | ||
|
||
// If the element is marked as collapsable, check for double click | ||
// to toggle the element visibility | ||
if (collapsable) { | ||
$resizeCont.on("mousedown", function (e) { | ||
toggle($element); | ||
}); | ||
} | ||
|
||
function endResize(e) { | ||
if (isMouseDown) { | ||
isMouseDown = false; | ||
$resizeCont.off("mousemove"); | ||
$resizeCont.remove(); | ||
$element.trigger("panelResizeEnd", [elementSizeFunction.apply($element)]); | ||
|
||
// We wait 100ms to remove the resizer container to capture a mousedown | ||
// on the container that would account for double click | ||
setTimeout(function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've been using |
||
$resizeCont.off("mousemove"); | ||
$resizeCont.off("mousedown"); | ||
$resizeCont.remove(); | ||
}, 100); | ||
} | ||
} | ||
|
||
|
@@ -174,7 +273,7 @@ define(function (require, exports, module) { | |
$(".vert-resizable").each(function (index, element) { | ||
|
||
if ($(element).hasClass("top-resizer")) { | ||
makeResizable(element, DIRECTION_VERTICAL, POSITION_TOP, DEFAULT_MIN_SIZE); | ||
makeResizable(element, DIRECTION_VERTICAL, POSITION_TOP, DEFAULT_MIN_SIZE, $(element).hasClass("collapsable")); | ||
} | ||
|
||
//if ($(element).hasClass("bottom-resizer")) { | ||
|
@@ -195,4 +294,7 @@ define(function (require, exports, module) { | |
}); | ||
|
||
exports.makeResizable = makeResizable; | ||
exports.toggle = toggle; | ||
exports.show = show; | ||
exports.hide = hide; | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be nice to have a setMinSize API so panels can have something different from the default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @redmunds Yes... I was planning to add it next, as it's required to finalize the sidebar refactor. Panels using the Would that be enough or do we still need an API to change the minSize at runtime? I would expect minSize to be set only during initialization... Should I add it now, or wait to do it with the sidebar refactor final step? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think data-minSize is probably a better solution because it eliminates the timing of calling an API method to set it. It's ok to wait until the sidebar refactoring. Also, I'm writing an extension that uses the bottom-panel with the resizer and I ran into the problem where I had to call makeResizable is not automatically called because extensions are not yet loaded when htmlReady() is called. I think this is fixed if you use appReady() instead. Let me know if you want me to send you a copy of the extension. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll be adding the About extensions, I also hit that same issue. I think scanning the DOM on @redmunds Please, send me a copy of your extension. I'd love to see it! I'll try to see if the Resizer module can be improved somehow to get a better workflow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo -- the event is "panelResizeStart"