diff options
Diffstat (limited to 'js/dojo-1.7.2/dojox/layout/ResizeHandle.js')
| -rw-r--r-- | js/dojo-1.7.2/dojox/layout/ResizeHandle.js | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/js/dojo-1.7.2/dojox/layout/ResizeHandle.js b/js/dojo-1.7.2/dojox/layout/ResizeHandle.js new file mode 100644 index 0000000..5986bc1 --- /dev/null +++ b/js/dojo-1.7.2/dojox/layout/ResizeHandle.js @@ -0,0 +1,364 @@ +//>>built +define("dojox/layout/ResizeHandle", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/connect","dojo/_base/array","dojo/_base/event", + "dojo/_base/fx","dojo/_base/window","dojo/fx","dojo/window","dojo/dom","dojo/dom-class", + "dojo/dom-geometry","dojo/dom-style","dijit/_base/manager","dijit/_Widget","dijit/_TemplatedMixin", + "dojo/_base/declare"], function ( + kernel, lang, connect, arrayUtil, eventUtil, fxBase, windowBase, fxUtil, windowUtil, + domUtil, domClass, domGeometry, domStyle, manager, Widget, TemplatedMixin, declare) { + +kernel.experimental("dojox.layout.ResizeHandle"); + +/*===== + var Widget = dijit._Widget; + var TemplatedMixin = dijit._TemplatedMixin; +=====*/ +var ResizeHandle = declare("dojox.layout.ResizeHandle",[Widget, TemplatedMixin], + { + // summary: A dragable handle used to resize an attached node. + // + // description: + // The handle on the bottom-right corner of FloatingPane or other widgets that allows + // the widget to be resized. + // Typically not used directly. + // + // targetId: String + // id of the Widget OR DomNode that I will size + targetId: "", + + // targetContainer: DomNode + // over-ride targetId and attch this handle directly to a reference of a DomNode + targetContainer: null, + + // resizeAxis: String + // one of: x|y|xy limit resizing to a single axis, default to xy ... + resizeAxis: "xy", + + // activeResize: Boolean + // if true, node will size realtime with mouse movement, + // if false, node will create virtual node, and only resize target on mouseUp + activeResize: false, + + // activeResizeClass: String + // css class applied to virtual resize node. + activeResizeClass: "dojoxResizeHandleClone", + + // animateSizing: Boolean + // only applicable if activeResize = false. onMouseup, animate the node to the + // new size + animateSizing: true, + + // animateMethod: String + // one of "chain" or "combine" ... visual effect only. combine will "scale" + // node to size, "chain" will alter width, then height + animateMethod: "chain", + + // animateDuration: Integer + // time in MS to run sizing animation. if animateMethod="chain", total animation + // playtime is 2*animateDuration + animateDuration: 225, + + // minHeight: Integer + // smallest height in px resized node can be + minHeight: 100, + + // minWidth: Integer + // smallest width in px resize node can be + minWidth: 100, + + // constrainMax: Boolean + // Toggle if this widget cares about the maxHeight and maxWidth + // parameters. + constrainMax: false, + + // maxHeight: Integer + // Largest height size in px the resize node can become. + maxHeight:0, + + // maxWidth: Integer + // Largest width size in px the reize node can become. + maxWidth:0, + + // fixedAspect: Boolean + // Toggle to enable this widget to maintain the aspect + // ratio of the attached node. + fixedAspect: false, + + // intermediateChanges: Boolean + // Toggle to enable/disable this widget from firing onResize + // events at every step of a resize. If `activeResize` is true, + // and this is false, onResize only fires _after_ the drop + // operation. Animated resizing is not affected by this setting. + intermediateChanges: false, + + // startTopic: String + // The name of the topic this resizehandle publishes when resize is starting + startTopic: "/dojo/resize/start", + + // endTopic: String + // The name of the topic this resizehandle publishes when resize is complete + endTopic:"/dojo/resize/stop", + + templateString: '<div dojoAttachPoint="resizeHandle" class="dojoxResizeHandle"><div></div></div>', + + postCreate: function(){ + // summary: setup our one major listener upon creation + this.connect(this.resizeHandle, "onmousedown", "_beginSizing"); + if(!this.activeResize){ + // there shall be only a single resize rubberbox that at the top + // level so that we can overlay it on anything whenever the user + // resizes something. Since there is only one mouse pointer he + // can't at once resize multiple things interactively. + this._resizeHelper = manager.byId('dojoxGlobalResizeHelper'); + if(!this._resizeHelper){ + this._resizeHelper = new _ResizeHelper({ + id: 'dojoxGlobalResizeHelper' + }).placeAt(windowBase.body()); + domClass.add(this._resizeHelper.domNode, this.activeResizeClass); + } + }else{ this.animateSizing = false; } + + if(!this.minSize){ + this.minSize = { w: this.minWidth, h: this.minHeight }; + } + + if(this.constrainMax){ + this.maxSize = { w: this.maxWidth, h: this.maxHeight } + } + + // should we modify the css for the cursor hover to n-resize nw-resize and w-resize? + this._resizeX = this._resizeY = false; + var addClass = lang.partial(domClass.add, this.resizeHandle); + switch(this.resizeAxis.toLowerCase()){ + case "xy" : + this._resizeX = this._resizeY = true; + // FIXME: need logic to determine NW or NE class to see + // based on which [todo] corner is clicked + addClass("dojoxResizeNW"); + break; + case "x" : + this._resizeX = true; + addClass("dojoxResizeW"); + break; + case "y" : + this._resizeY = true; + addClass("dojoxResizeN"); + break; + } + }, + + _beginSizing: function(/*Event*/ e){ + // summary: setup movement listeners and calculate initial size + + if(this._isSizing){ return; } + + connect.publish(this.startTopic, [ this ]); + this.targetWidget = manager.byId(this.targetId); + + this.targetDomNode = this.targetWidget ? this.targetWidget.domNode : domUtil.byId(this.targetId); + if(this.targetContainer){ this.targetDomNode = this.targetContainer; } + if(!this.targetDomNode){ return; } + + if(!this.activeResize){ + var c = domGeometry.position(this.targetDomNode, true); + this._resizeHelper.resize({l: c.x, t: c.y, w: c.w, h: c.h}); + this._resizeHelper.show(); + } + + this._isSizing = true; + this.startPoint = { x:e.clientX, y:e.clientY }; + + // widget.resize() or setting style.width/height expects native box model dimension + // (in most cases content-box, but it may be border-box if in backcompact mode) + var style = domStyle.getComputedStyle(this.targetDomNode), + borderModel = domGeometry.boxModel==='border-model', + padborder = borderModel?{w:0,h:0}:domGeometry.getPadBorderExtents(this.targetDomNode, style), + margin = domGeometry.getMarginExtents(this.targetDomNode, style), + mb; + mb = this.startSize = { + w: domStyle.get(this.targetDomNode, 'width', style), + h: domStyle.get(this.targetDomNode, 'height', style), + //ResizeHelper.resize expects a bounding box of the + //border box, so let's keep track of padding/border + //width/height as well + pbw: padborder.w, pbh: padborder.h, + mw: margin.w, mh: margin.h}; + + this._pconnects = [ + connect.connect(windowBase.doc,"onmousemove",this,"_updateSizing"), + connect.connect(windowBase.doc,"onmouseup", this, "_endSizing") + ]; + + eventUtil.stop(e); + }, + + _updateSizing: function(/*Event*/ e){ + // summary: called when moving the ResizeHandle ... determines + // new size based on settings/position and sets styles. + + if(this.activeResize){ + this._changeSizing(e); + }else{ + var tmp = this._getNewCoords(e, 'border'); + if(tmp === false){ return; } + this._resizeHelper.resize(tmp); + } + e.preventDefault(); + }, + + _getNewCoords: function(/* Event */ e, /* String */ box){ + + // On IE, if you move the mouse above/to the left of the object being resized, + // sometimes clientX/Y aren't set, apparently. Just ignore the event. + try{ + if(!e.clientX || !e.clientY){ return false; } + }catch(e){ + // sometimes you get an exception accessing above fields... + return false; + } + this._activeResizeLastEvent = e; + + var dx = (this.isLeftToRight()?1:-1) * (this.startPoint.x - e.clientX), + dy = this.startPoint.y - e.clientY, + newW = this.startSize.w - (this._resizeX ? dx : 0), + newH = this.startSize.h - (this._resizeY ? dy : 0), + r = this._checkConstraints(newW, newH) + ; + + switch(box){ + case 'margin': + r.w += this.startSize.mw; + r.h += this.startSize.mh; + //pass through + case "border": + r.w += this.startSize.pbw; + r.h += this.startSize.pbh; + break; + //default: //native, do nothing + } + + return r; // Object + }, + + _checkConstraints: function(newW, newH){ + // summary: filter through the various possible constaint possibilities. + + // minimum size check + if(this.minSize){ + var tm = this.minSize; + if(newW < tm.w){ + newW = tm.w; + } + if(newH < tm.h){ + newH = tm.h; + } + } + + // maximum size check: + if(this.constrainMax && this.maxSize){ + var ms = this.maxSize; + if(newW > ms.w){ + newW = ms.w; + } + if(newH > ms.h){ + newH = ms.h; + } + } + + if(this.fixedAspect){ + var w = this.startSize.w, h = this.startSize.h, + delta = w * newH - h * newW; + if(delta<0){ + newW = newH * w / h; + }else if(delta>0){ + newH = newW * h / w; + } + } + + return { w: newW, h: newH }; // Object + }, + + _changeSizing: function(/*Event*/ e){ + // summary: apply sizing information based on information in (e) to attached node + + var isWidget = this.targetWidget && lang.isFunction(this.targetWidget.resize), + tmp = this._getNewCoords(e, isWidget && 'margin'); + if(tmp === false){ return; } + + if(isWidget){ + this.targetWidget.resize(tmp); + }else{ + if(this.animateSizing){ + var anim = fxUtil[this.animateMethod]([ + fxBase.animateProperty({ + node: this.targetDomNode, + properties: { + width: { start: this.startSize.w, end: tmp.w } + }, + duration: this.animateDuration + }), + fxBase.animateProperty({ + node: this.targetDomNode, + properties: { + height: { start: this.startSize.h, end: tmp.h } + }, + duration: this.animateDuration + }) + ]); + anim.play(); + }else{ + domStyle.set(this.targetDomNode,{ + width: tmp.w + "px", + height: tmp.h + "px" + }); + } + } + if(this.intermediateChanges){ + this.onResize(e); + } + }, + + _endSizing: function(/*Event*/ e){ + // summary: disconnect listenrs and cleanup sizing + arrayUtil.forEach(this._pconnects, connect.disconnect); + var pub = lang.partial(connect.publish, this.endTopic, [ this ]); + if(!this.activeResize){ + this._resizeHelper.hide(); + this._changeSizing(e); + setTimeout(pub, this.animateDuration + 15); + }else{ + pub(); + } + this._isSizing = false; + this.onResize(e); + }, + + onResize: function(e){ + // summary: Stub fired when sizing is done. Fired once + // after resize, or often when `intermediateChanges` is + // set to true. + } + +}); + +var _ResizeHelper = dojo.declare("dojox.layout._ResizeHelper", Widget, { + // summary: A global private resize helper shared between any + // `dojox.layout.ResizeHandle` with activeSizing off. + + show: function(){ + // summary: show helper to start resizing + domStyle.set(this.domNode, "display", ""); + }, + + hide: function(){ + // summary: hide helper after resizing is complete + domStyle.set(this.domNode, "display", "none"); + }, + + resize: function(/* Object */dim){ + // summary: size the widget and place accordingly + domGeometry.setMarginBox(this.domNode, dim); + } + +}); +return ResizeHandle; +}); |
