diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index 89504e36366..6de1dd716db 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -123,6 +123,36 @@ test("aspectRatio: 'preserve' (ne)", function() { equal( target.height(), 70, "compare minHeight"); }); +test( "aspectRatio: Resizing can move objects", function() { + expect( 7 ); + // http://bugs.jqueryui.com/ticket/7018 - Resizing can move objects + var handleW = ".ui-resizable-w", + handleNW = ".ui-resizable-nw", + target = $( "#resizable1" ).resizable({ + aspectRatio: true, + handles: "all", + containment: "parent" + }); + + $( "#container" ).css({ width: 200, height: 300 }); + $( "#resizable1" ).css({ width: 100, height: 100, left: 75, top: 200 }); + + TestHelpers.resizable.drag( handleW, -20 ); + equal( target.width(), 100, "compare width - no size change" ); + equal( target.height(), 100, "compare height - no size change" ); + equal( target.position().left, 75, "compare left - no movement" ); + + // http://bugs.jqueryui.com/ticket/9107 - aspectRatio and containment not handled correctly + $( "#container" ).css({ width: 200, height: 300, position: "absolute", left: 100, top: 100 }); + $( "#resizable1" ).css({ width: 100, height: 100, left: 0, top: 0 }); + + TestHelpers.resizable.drag( handleNW, -20, -20 ); + equal( target.width(), 100, "compare width - no size change" ); + equal( target.height(), 100, "compare height - no size change" ); + equal( target.position().left, 0, "compare left - no movement" ); + equal( target.position().top, 0, "compare top - no movement" ); +}); + test( "containment", function() { expect( 4 ); var element = $( "#resizable1" ).resizable({ diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index 040f029f968..b8a9d40fae2 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -53,7 +53,6 @@ $.widget("ui.resizable", $.ui.mouse, { _hasScroll: function( el, a ) { - //If overflow is hidden, the element might have extra content, but the user wants to hide it if ( $( el ).css( "overflow" ) === "hidden") { return false; } @@ -89,10 +88,9 @@ $.widget("ui.resizable", $.ui.mouse, { _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null }); - //Wrap the element if it cannot hold child nodes + // Wrap the element if it cannot hold child nodes if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { - //Create a wrapper element and set the wrapper to the new current internal element this.element.wrap( $("
").css({ position: this.element.css("position"), @@ -103,30 +101,26 @@ $.widget("ui.resizable", $.ui.mouse, { }) ); - //Overwrite the original this.element this.element = this.element.parent().data( "ui-resizable", this.element.resizable( "instance" ) ); this.elementIsWrapper = true; - //Move margins to the wrapper this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); - - //Prevent Safari textarea resize + // support: Safari + // Prevent Safari textarea resize this.originalResizeStyle = this.originalElement.css("resize"); this.originalElement.css("resize", "none"); - //Push the actual element to our proportionallyResize internal array this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); + // support: IE9 // avoid IE jump (hard set the margin) this.originalElement.css({ margin: this.originalElement.css("margin") }); - // fix handlers offset this._proportionallyResize(); - } this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" }); @@ -145,15 +139,13 @@ $.widget("ui.resizable", $.ui.mouse, { hname = "ui-resizable-"+handle; axis = $(""); - // Apply zIndex to all handles - see #7960 axis.css({ zIndex: o.zIndex }); - //TODO : What's going on here? + // TODO : What's going on here? if ("se" === handle) { axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); } - //Insert into internal handles object and append to element this.handles[handle] = ".ui-resizable-"+handle; this.element.append(axis); } @@ -172,15 +164,12 @@ $.widget("ui.resizable", $.ui.mouse, { this.handles[i] = $(this.handles[i], this.element).show(); } - //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { axis = $(this.handles[i], this.element); - //Checking the correct pad and border padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); - //The padding type i have to apply... padPos = [ "padding", /ne|nw|n/.test(i) ? "Top" : /se|sw|s/.test(i) ? "Bottom" : @@ -192,31 +181,28 @@ $.widget("ui.resizable", $.ui.mouse, { } - //TODO: What's that good for? There's not anything to be executed left + // TODO: What's that good for? There's not anything to be executed left if(!$(this.handles[i]).length) { continue; } } }; - //TODO: make renderAxis a prototype function + // TODO: make renderAxis a prototype function this._renderAxis(this.element); this._handles = $(".ui-resizable-handle", this.element) .disableSelection(); - //Matching axis name this._handles.mouseover(function() { if (!that.resizing) { if (this.className) { axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); } - //Axis, default = se that.axis = axis && axis[1] ? axis[1] : "se"; } }); - //If we want to auto hide the elements if (o.autoHide) { this._handles.hide(); $(this.element) @@ -239,7 +225,6 @@ $.widget("ui.resizable", $.ui.mouse, { }); } - //Initialize the mouse interaction this._mouseInit(); }, @@ -254,7 +239,7 @@ $.widget("ui.resizable", $.ui.mouse, { .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); }; - //TODO: Unwrap at same DOM position + // TODO: Unwrap at same DOM position if (this.elementIsWrapper) { _destroy(this.element); wrapper = this.element; @@ -297,7 +282,7 @@ $.widget("ui.resizable", $.ui.mouse, { this.resizing = true; - // bugfix for http://dev.jquery.com/ticket/1749 + // Bugfix for http://bugs.jqueryui.com/ticket/1749 if ( (/absolute/).test( el.css("position") ) ) { el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); } else if (el.is(".ui-draggable")) { @@ -314,7 +299,6 @@ $.widget("ui.resizable", $.ui.mouse, { curtop += $(o.containment).scrollTop() || 0; } - //Store needed variables this.offset = this.helper.offset(); this.position = { left: curleft, top: curtop }; this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() }; @@ -323,7 +307,6 @@ $.widget("ui.resizable", $.ui.mouse, { this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; this.originalMousePosition = { left: event.pageX, top: event.pageY }; - //Aspect Ratio this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); cursor = $(".ui-resizable-" + this.axis).css("cursor"); @@ -336,27 +319,29 @@ $.widget("ui.resizable", $.ui.mouse, { _mouseDrag: function(event) { - //Increase performance, avoid regex var data, el = this.helper, props = {}, smp = this.originalMousePosition, a = this.axis, - prevTop = this.position.top, - prevLeft = this.position.left, - prevWidth = this.size.width, - prevHeight = this.size.height, dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0, trigger = this._change[a]; + this.prevPosition = { + top: this.position.top, + left: this.position.left + }; + this.prevSize = { + width: this.size.width, + height: this.size.height + }; + if (!trigger) { return false; } - // Calculate the attrs that will be change data = trigger.apply(this, [event, dx, dy]); - // Put this in the mouseDrag handler since the user can start pressing shift while resizing this._updateVirtualBoundaries(event.shiftKey); if (this._aspectRatio || event.shiftKey) { data = this._updateRatio(data, event); @@ -366,30 +351,28 @@ $.widget("ui.resizable", $.ui.mouse, { this._updateCache(data); - // plugins callbacks need to be called first this._propagate("resize", event); - if (this.position.top !== prevTop) { + if ( this.position.top !== this.prevPosition.top ) { props.top = this.position.top + "px"; } - if (this.position.left !== prevLeft) { + if ( this.position.left !== this.prevPosition.left ) { props.left = this.position.left + "px"; } - if (this.size.width !== prevWidth) { + if ( this.size.width !== this.prevSize.width ) { props.width = this.size.width + "px"; } - if (this.size.height !== prevHeight) { + if ( this.size.height !== this.prevSize.height ) { props.height = this.size.height + "px"; } - el.css(props); + el.css( props ); - if (!this._helper && this._proportionallyResizeElements.length) { + if ( !this._helper && this._proportionallyResizeElements.length ) { this._proportionallyResize(); } - // Call the user callback if the element was resized - if ( ! $.isEmptyObject(props) ) { - this._trigger("resize", event, this.ui()); + if ( !$.isEmptyObject( props ) ) { + this._trigger( "resize", event, this.ui() ); } return false; @@ -450,8 +433,6 @@ $.widget("ui.resizable", $.ui.mouse, { }; if(this._aspectRatio || forceAspectRatio) { - // We want to create an enclosing box whose aspect ration is the requested one - // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension pMinWidth = b.minHeight * this.aspectRatio; pMinHeight = b.minWidth / this.aspectRatio; pMaxWidth = b.maxHeight * this.aspectRatio; @@ -548,7 +529,7 @@ $.widget("ui.resizable", $.ui.mouse, { data.top = dh - o.maxHeight; } - // fixing jump error on top/left - bug #2330 + // Fixing jump error on top/left - bug #2330 if (!data.width && !data.height && !data.left && data.top) { data.top = null; } else if (!data.width && !data.height && !data.top && data.left) { @@ -662,7 +643,9 @@ $.widget("ui.resizable", $.ui.mouse, { position: this.position, size: this.size, originalSize: this.originalSize, - originalPosition: this.originalPosition + originalPosition: this.originalPosition, + prevSize: this.prevSize, + prevPosition: this.prevPosition }; } @@ -737,10 +720,7 @@ $.ui.plugin.add("resizable", "containment", { element: $(document), left: 0, top: 0, width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight }; - } - - // i'm a node, so compute top, left, right, bottom - else { + } else { element = $(ce); p = []; $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = that._num(element.css("padding" + name)); }); @@ -761,13 +741,19 @@ $.ui.plugin.add("resizable", "containment", { } }, - resize: function( event ) { - var woset, hoset, isParent, isOffsetRelative, + resize: function( event, ui ) { + var woset, + hoset, + isParent, + isOffsetRelative, that = $(this).resizable( "instance" ), o = that.options, - co = that.containerOffset, cp = that.position, + co = that.containerOffset, + cp = that.position, pRatio = that._aspectRatio || event.shiftKey, - cop = { top:0, left:0 }, ce = that.containerElement; + cop = { top:0, left:0 }, + ce = that.containerElement, + continueResize = true; if (ce[0] !== document && (/static/).test(ce.css("position"))) { cop = co; @@ -777,6 +763,7 @@ $.ui.plugin.add("resizable", "containment", { that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); if (pRatio) { that.size.height = that.size.width / that.aspectRatio; + continueResize = false; } that.position.left = o.helper ? co.left : 0; } @@ -785,6 +772,7 @@ $.ui.plugin.add("resizable", "containment", { that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); if (pRatio) { that.size.width = that.size.height * that.aspectRatio; + continueResize = false; } that.position.top = that._helper ? co.top : 0; } @@ -802,19 +790,28 @@ $.ui.plugin.add("resizable", "containment", { woset -= Math.abs( that.parentData.left ); } - if (woset + that.size.width >= that.parentData.width) { + if ( woset + that.size.width >= that.parentData.width ) { that.size.width = that.parentData.width - woset; if (pRatio) { that.size.height = that.size.width / that.aspectRatio; + continueResize = false; } } - if (hoset + that.size.height >= that.parentData.height) { + if ( hoset + that.size.height >= that.parentData.height ) { that.size.height = that.parentData.height - hoset; if (pRatio) { that.size.width = that.size.height * that.aspectRatio; + continueResize = false; } } + + if ( !continueResize ){ + that.position.left = ui.prevPosition.left; + that.position.top = ui.prevPosition.top; + that.size.width = ui.prevSize.width; + that.size.height = ui.prevSize.height; + } }, stop: function(){