resize-base.js revision cc1d4edffd5ecfd11d5b68c5d24988d0cfb2371a
6a67d144095c31bbafed93cec1619590157335eajvergara * The Resize Utility allows you to make an HTML element resizable.
6a67d144095c31bbafed93cec1619590157335eajvergara * @module resize
6a67d144095c31bbafed93cec1619590157335eajvergara isNode = function(v) {
6a67d144095c31bbafed93cec1619590157335eajvergara return (v instanceof Y.Node);
6a67d144095c31bbafed93cec1619590157335eajvergara concat = function() {
6a67d144095c31bbafed93cec1619590157335eajvergara return Array.prototype.slice.call(arguments).join(SPACE);
0142bbb7ccb5d0efb942c20f5d27e5ddfb4344fdkenneth_suter return str.substring(0, 1).toUpperCase() + str.substring(1);
6a67d144095c31bbafed93cec1619590157335eajvergara CSS_RESIZE_HANDLE_ACTIVE = getCN(RESIZE, HANDLE, ACTIVE),
857225469c51bedb8c0566aa7757800cfaac4075kenneth_suter CSS_RESIZE_HANDLE_INNER = getCN(RESIZE, HANDLE, INNER),
0142bbb7ccb5d0efb942c20f5d27e5ddfb4344fdkenneth_suter CSS_RESIZE_HANDLE_INNER_PLACEHOLDER = getCN(RESIZE, HANDLE, INNER, HANDLE_SUB),
0142bbb7ccb5d0efb942c20f5d27e5ddfb4344fdkenneth_suter CSS_RESIZE_HANDLE_PLACEHOLDER = getCN(RESIZE, HANDLE, HANDLE_SUB),
6a67d144095c31bbafed93cec1619590157335eajvergara CSS_RESIZE_HIDDEN_HANDLES = getCN(RESIZE, HIDDEN, HANDLES),
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * A base class for Resize, providing:
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suter * <li>Basic Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
6a67d144095c31bbafed93cec1619590157335eajvergara * <li>Applies drag handles to an element to make it resizable</li>
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * <li>Here is the list of valid resize handles:
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * <code>[ 't', 'tr', 'r', 'br', 'b', 'bl', 'l', 'tl' ]</code>. You can
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * read this list as top, top-right, right, bottom-right, bottom,
6a67d144095c31bbafed93cec1619590157335eajvergara * bottom-left, left, top-left.</li>
6a67d144095c31bbafed93cec1619590157335eajvergara * <li>The drag handles are inserted into the element and positioned
5b9085a87d43ed3ae0b149a9c79ba57723733185jvergara * absolute. Some elements, such as a textarea or image, don't support
c6c8254710feb80354037c2afb8d1cdae930a27akenneth_suter * children. To overcome that, set wrap:true in your config and the
6a67d144095c31bbafed93cec1619590157335eajvergara * element willbe wrapped for you automatically.</li>
6a67d144095c31bbafed93cec1619590157335eajvergara * Quick Example:
6a67d144095c31bbafed93cec1619590157335eajvergara * <pre><code>var instance = new Y.Resize({
6a67d144095c31bbafed93cec1619590157335eajvergara * node: '#resize1',
6a67d144095c31bbafed93cec1619590157335eajvergara * proxy: true,
6a67d144095c31bbafed93cec1619590157335eajvergara * preserveRatio: true,
6a67d144095c31bbafed93cec1619590157335eajvergara * wrap: true,
6a67d144095c31bbafed93cec1619590157335eajvergara * maxHeight: 170,
a7d59bf59f3b588e70b86d920e0ab271496f4f06kenneth_suter * maxWidth: 400,
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * handles: 't, tr, r, br, b, bl, l, tl'
6a67d144095c31bbafed93cec1619590157335eajvergara * </code></pre>
6a67d144095c31bbafed93cec1619590157335eajvergara * Check the list of <a href="Resize.html#configattributes">Configuration Attributes</a> available for
2401d3c2af505789c7c3b860a43e973f27731243jvergara * @class Resize
2401d3c2af505789c7c3b860a43e973f27731243jvergara * @param config {Object} Object literal specifying widget configuration properties.
2401d3c2af505789c7c3b860a43e973f27731243jvergara * @constructor
2401d3c2af505789c7c3b860a43e973f27731243jvergara * @extends Base
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter Resize.superclass.constructor.apply(this, arguments);
2401d3c2af505789c7c3b860a43e973f27731243jvergara * Static property provides a string to identify the class.
a7d59bf59f3b588e70b86d920e0ab271496f4f06kenneth_suter * @property Resize.NAME
2401d3c2af505789c7c3b860a43e973f27731243jvergara * @type String
6a67d144095c31bbafed93cec1619590157335eajvergara * Static property used to define the default attribute
0877596da3b90efc5fd39171cef80a2fb8ec395ekenneth_suter * configuration for the Resize.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property Resize.ATTRS
3e6ff045d382a718a951d6305c8910ffc268f893kenneth_suter * @type Object
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara * Stores the active handle during the resize.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute activeHandle
6a67d144095c31bbafed93cec1619590157335eajvergara * @default null
6a67d144095c31bbafed93cec1619590157335eajvergara * @type String
6a67d144095c31bbafed93cec1619590157335eajvergara * Stores the active handle element during the resize.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute activeHandleNode
6a67d144095c31bbafed93cec1619590157335eajvergara * @default null
c9d984b0d2c0fda320e79eb3868dd6fbeb1ffa34jvergara * False to ensure that the resize handles are always visible, true to
6a67d144095c31bbafed93cec1619590157335eajvergara * display them only when the user mouses over the resizable borders.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute autoHide
6a67d144095c31bbafed93cec1619590157335eajvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
6a67d144095c31bbafed93cec1619590157335eajvergara * The default minimum height of the element. Only used when
6a67d144095c31bbafed93cec1619590157335eajvergara * ResizeConstrained is not plugged.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute defMinHeight
6a67d144095c31bbafed93cec1619590157335eajvergara * @default 15
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Number
a7d59bf59f3b588e70b86d920e0ab271496f4f06kenneth_suter * The default minimum width of the element. Only used when
6a67d144095c31bbafed93cec1619590157335eajvergara * ResizeConstrained is not plugged.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute defMinWidth
6a67d144095c31bbafed93cec1619590157335eajvergara * @default 15
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Number
6a67d144095c31bbafed93cec1619590157335eajvergara * The handles to use (any combination of): 't', 'b', 'r', 'l', 'bl',
6a67d144095c31bbafed93cec1619590157335eajvergara * 'br', 'tl', 'tr'. Can use a shortcut of All.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute handles
6a67d144095c31bbafed93cec1619590157335eajvergara * @default all
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Array | String
6a67d144095c31bbafed93cec1619590157335eajvergara * The selector or element to resize. Required.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute node
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Node
2401d3c2af505789c7c3b860a43e973f27731243jvergara * Resize a proxy element instead of the real element.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute proxy
6a67d144095c31bbafed93cec1619590157335eajvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
6a67d144095c31bbafed93cec1619590157335eajvergara * The Resize proxy element.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute proxyNode
6a67d144095c31bbafed93cec1619590157335eajvergara * @default Generated using an internal HTML markup
6a67d144095c31bbafed93cec1619590157335eajvergara * @type String | Node
6a67d144095c31bbafed93cec1619590157335eajvergara valueFn: function() {
6a67d144095c31bbafed93cec1619590157335eajvergara * True when the element is being Resized.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute resizing
6a67d144095c31bbafed93cec1619590157335eajvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
6a67d144095c31bbafed93cec1619590157335eajvergara * True to wrap an element with a div if needed (required for textareas
6a67d144095c31bbafed93cec1619590157335eajvergara * and images, defaults to false) in favor of the handles config option.
6a67d144095c31bbafed93cec1619590157335eajvergara * The wrapper element type (default div) could be over-riden passing the
6a67d144095c31bbafed93cec1619590157335eajvergara * <code>wrapper</code> attribute.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute wrap
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
6a67d144095c31bbafed93cec1619590157335eajvergara * Elements that requires a wrapper by default. Normally are elements
6a67d144095c31bbafed93cec1619590157335eajvergara * which cannot have children elements.
6a67d144095c31bbafed93cec1619590157335eajvergara * @attribute wrapTypes
6a67d144095c31bbafed93cec1619590157335eajvergara * @default /canvas|textarea|input|select|button|img/i
6a67d144095c31bbafed93cec1619590157335eajvergara * @readOnly
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Regex
6a67d144095c31bbafed93cec1619590157335eajvergara value: /^canvas|textarea|input|select|button|img|iframe|table|embed$/i
c9d984b0d2c0fda320e79eb3868dd6fbeb1ffa34jvergara * Element to wrap the <code>wrapTypes</code>. This element will house
c9d984b0d2c0fda320e79eb3868dd6fbeb1ffa34jvergara * the handles elements.
c9d984b0d2c0fda320e79eb3868dd6fbeb1ffa34jvergara * @attribute wrapper
6a67d144095c31bbafed93cec1619590157335eajvergara * @default div
c9d984b0d2c0fda320e79eb3868dd6fbeb1ffa34jvergara * @type String | Node
6a67d144095c31bbafed93cec1619590157335eajvergara * @writeOnce
6a67d144095c31bbafed93cec1619590157335eajvergara * Array containing all possible resizable handles.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property ALL_HANDLES
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * @type {String}
6a67d144095c31bbafed93cec1619590157335eajvergara * Regex which matches with the handles that could change the height of
6a67d144095c31bbafed93cec1619590157335eajvergara * the resizable element.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property REGEX_CHANGE_HEIGHT
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * Regex which matches with the handles that could change the left of
0142bbb7ccb5d0efb942c20f5d27e5ddfb4344fdkenneth_suter * the resizable element.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property REGEX_CHANGE_LEFT
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
6a67d144095c31bbafed93cec1619590157335eajvergara * Regex which matches with the handles that could change the top of
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * the resizable element.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property REGEX_CHANGE_TOP
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
6a67d144095c31bbafed93cec1619590157335eajvergara * Regex which matches with the handles that could change the width of
6a67d144095c31bbafed93cec1619590157335eajvergara * the resizable element.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property REGEX_CHANGE_WIDTH
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
6a67d144095c31bbafed93cec1619590157335eajvergara * Template used to create the resize wrapper node when needed.
0142bbb7ccb5d0efb942c20f5d27e5ddfb4344fdkenneth_suter * @property WRAP_TEMPLATE
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
6a67d144095c31bbafed93cec1619590157335eajvergara WRAP_TEMPLATE: '<div class="'+CSS_RESIZE_WRAPPER+'"></div>',
6a67d144095c31bbafed93cec1619590157335eajvergara * Template used to create the resize proxy.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property PROXY_TEMPLATE
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
6a67d144095c31bbafed93cec1619590157335eajvergara PROXY_TEMPLATE: '<div class="'+CSS_RESIZE_PROXY+'"></div>',
6a67d144095c31bbafed93cec1619590157335eajvergara * Template used to create each resize handle.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property HANDLE_TEMPLATE
6a67d144095c31bbafed93cec1619590157335eajvergara * @type {String}
2401d3c2af505789c7c3b860a43e973f27731243jvergara HANDLE_TEMPLATE: '<div class="'+concat(CSS_RESIZE_HANDLE, CSS_RESIZE_HANDLE_PLACEHOLDER)+'">' +
2401d3c2af505789c7c3b860a43e973f27731243jvergara '<div class="'+concat(CSS_RESIZE_HANDLE_INNER, CSS_RESIZE_HANDLE_INNER_PLACEHOLDER)+'"> </div>' +
6a67d144095c31bbafed93cec1619590157335eajvergara * Whether the handle being dragged can change the height.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property changeHeightHandles
6a67d144095c31bbafed93cec1619590157335eajvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
6a67d144095c31bbafed93cec1619590157335eajvergara * Whether the handle being dragged can change the left.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property changeLeftHandles
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
7b6b125d52edabd5b1c9134feef7aeae0e69499ekenneth_suter * Whether the handle being dragged can change the top.
7b6b125d52edabd5b1c9134feef7aeae0e69499ekenneth_suter * @property changeTopHandles
6a67d144095c31bbafed93cec1619590157335eajvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * Whether the handle being dragged can change the width.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property changeWidthHandles
6a67d144095c31bbafed93cec1619590157335eajvergara * @default false
6a67d144095c31bbafed93cec1619590157335eajvergara * @type boolean
6a67d144095c31bbafed93cec1619590157335eajvergara * Store DD.Delegate reference for the respective Resize instance.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property delegate
6a67d144095c31bbafed93cec1619590157335eajvergara * @default null
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Object
6a67d144095c31bbafed93cec1619590157335eajvergara * Stores the current values for the height, width, top and left. You are
6a67d144095c31bbafed93cec1619590157335eajvergara * able to manipulate these values on resize in order to change the resize
6a67d144095c31bbafed93cec1619590157335eajvergara * behavior.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property info
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Object
6a67d144095c31bbafed93cec1619590157335eajvergara * @protected
6a67d144095c31bbafed93cec1619590157335eajvergara * Stores the last values for the height, width, top and left.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property lastInfo
6a67d144095c31bbafed93cec1619590157335eajvergara * @type Object
6a67d144095c31bbafed93cec1619590157335eajvergara * @protected
6a67d144095c31bbafed93cec1619590157335eajvergara * Stores the original values for the height, width, top and left, stored
6a67d144095c31bbafed93cec1619590157335eajvergara * on resize start.
6a67d144095c31bbafed93cec1619590157335eajvergara * @property originalInfo
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter * @type Object
6a67d144095c31bbafed93cec1619590157335eajvergara * @protected
7b6b125d52edabd5b1c9134feef7aeae0e69499ekenneth_suter * Construction logic executed during Resize instantiation. Lifecycle.
6a67d144095c31bbafed93cec1619590157335eajvergara * @method initializer
6a67d144095c31bbafed93cec1619590157335eajvergara * @protected
6a67d144095c31bbafed93cec1619590157335eajvergara initializer: function() {
6a67d144095c31bbafed93cec1619590157335eajvergara * Create the DOM structure for the Resize. Lifecycle.
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara * @method renderUI
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara * @protected
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara renderUI: function() {
bindUI: function() {
var instance = this;
syncUI: function() {
var instance = this;
destructor: function() {
var instance = this,
if (pNode) {
renderer: function() {
this.renderUI();
this.bindUI();
this.syncUI();
var instance = this;
Y.each(
function(handle, i) {
_bindDD: function() {
var instance = this;
dragConfig: {
useShim: true,
move: false
target: false
_bindHandle: function() {
var instance = this,
wrapper.delegate('mouseenter', Y.bind(instance._onHandleMouseEnter, instance), DOT+CSS_RESIZE_HANDLE);
wrapper.delegate('mouseleave', Y.bind(instance._onHandleMouseLeave, instance), DOT+CSS_RESIZE_HANDLE);
_createEvents: function() {
var instance = this,
queuable: false,
emitFacade: true,
bubbles: true,
_renderHandles: function() {
var instance = this,
* Render the <a href="Resize.html#config_proxyNode">proxyNode</a> element and
* make it sibling of the <a href="Resize.html#config_node">node</a>.
_renderProxy: function() {
var instance = this,
var instance = this;
* <a href="Resize.html#property_info">info</a> to respect the
var instance = this,
// forcing the offsetHeight/offsetWidth to be the passed size
// predicting, based on the original information, the last left valid in case of reach the min/max dimension
* Copy relevant styles of the <a href="Resize.html#config_node">node</a>
* to the <a href="Resize.html#config_wrapper">wrapper</a>.
nodeStyle = {},
wrapperStyle = {
function(node) {
* <p>Generates metadata to the <a href="Resize.html#property_info">info</a>
* and <a href="Resize.html#property_originalInfo">originalInfo</a></p>
var actXY,
if (event) {
_resize: function() {
var instance = this,
rules = {
tr: function() {
br: function() {
tl: function() {
bl: function() {
* <a href="Resize.html#property_info">info</a>.
_syncUI: function() {
var instance = this,
* <a href="Resize.html#property_info">info</a>.
_syncProxyUI: function() {
var instance = this,
var instance = this;
* Update <a href="Resize.html#property_info">info</a> values (bottom, actXY, left, top, offsetHeight, offsetWidth, right).
var instance = this;
var instance = this,
if (activeHandleNode) {
if (val) {
function(handleEl) {
var instance = this,
handles = [];
Y.each(
function(node, i) {
return handles;
var instance = this,
if (val) {
var instance = this,
val = true;
return val;
var instance = this;
var instance = this;
var instance = this,
var instance = this;
* Mouseenter event handler for the <a href="Resize.html#config_wrapper">wrapper</a>.
var instance = this;
* Mouseleave event handler for the <a href="Resize.html#config_wrapper">wrapper</a>.
var instance = this;
var instance = this,
var instance = this;
_valueWrapper: function() {
var instance = this,
if (pNode) {
return wrapper;
setter: function() {
value: null,
writeOnce: true