ResizeHandle.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. if (!dojo._hasResource["dojox.layout.ResizeHandle"]) { // _hasResource checks
  2. // added by build. Do
  3. // not use _hasResource
  4. // directly in your
  5. // code.
  6. dojo._hasResource["dojox.layout.ResizeHandle"] = true;
  7. dojo.provide("dojox.layout.ResizeHandle");
  8. dojo.experimental("dojox.layout.ResizeHandle");
  9. dojo.require("dijit._Widget");
  10. dojo.require("dijit._Templated");
  11. dojo.require("dojo.fx");
  12. dojo.declare("dojox.layout.ResizeHandle",
  13. [dijit._Widget, dijit._Templated], {
  14. // summary
  15. // The handle on the bottom-right corner of FloatingPane or
  16. // other widgets that allows
  17. // the widget to be resized.
  18. // Typically not used directly.
  19. // targetId: String
  20. // id of the Widget OR DomNode that I will size
  21. targetId : '',
  22. // targetContainer: DomNode
  23. // over-ride targetId and attch this handle directly to a
  24. // reference of a DomNode
  25. targetContainer : null,
  26. // resizeAxis: String
  27. // one of: x|y|xy limit resizing to a single axis, default to xy
  28. // ...
  29. resizeAxis : "xy",
  30. // activeResize: Boolean
  31. // if true, node will size realtime with mouse movement,
  32. // if false, node will create virtual node, and only resize
  33. // target on mouseUp
  34. activeResize : false,
  35. // activeResizeClass: String
  36. // css class applied to virtual resize node.
  37. activeResizeClass : 'dojoxResizeHandleClone',
  38. // animateSizing: Boolean
  39. // only applicable if activeResize = false. onMouseup, animate
  40. // the node to the
  41. // new size
  42. animateSizing : true,
  43. // animateMethod: String
  44. // one of "chain" or "combine" ... visual effect only. combine
  45. // will "scale"
  46. // node to size, "chain" will alter width, then height
  47. animateMethod : 'chain',
  48. // animateDuration: Integer
  49. // time in MS to run sizing animation. if animateMethod="chain",
  50. // total animation
  51. // playtime is 2*animateDuration
  52. animateDuration : 225,
  53. // minHeight: Integer
  54. // smallest height in px resized node can be
  55. minHeight : 100,
  56. // minWidth: Integer
  57. // smallest width in px resize node can be
  58. minWidth : 100,
  59. // resize handle template, fairly easy to override:
  60. templateString : '<div dojoAttachPoint="resizeHandle" class="dojoxResizeHandle"><div></div></div>',
  61. // private propteries and holders
  62. _isSizing : false,
  63. _connects : [],
  64. _activeResizeNode : null,
  65. _activeResizeLastEvent : null,
  66. // defaults to match default resizeAxis. set resizeAxis variable
  67. // to modify.
  68. _resizeX : true,
  69. _resizeY : true,
  70. postCreate : function() {
  71. // summary: setup our one major listener upon creation
  72. dojo.connect(this.resizeHandle, "onmousedown", this,
  73. "_beginSizing");
  74. if (!this.activeResize) {
  75. this._activeResizeNode = document.createElement('div');
  76. dojo.addClass(this._activeResizeNode,
  77. this.activeResizeClass);
  78. } else {
  79. this.animateSizing = false;
  80. }
  81. if (!this.minSize) {
  82. this.minSize = {
  83. w : this.minWidth,
  84. h : this.minHeight
  85. };
  86. }
  87. // should we modify the css for the cursor hover to n-resize
  88. // nw-resize and w-resize?
  89. this._resizeX = this._resizeY = false;
  90. switch (this.resizeAxis.toLowerCase()) {
  91. case "xy" :
  92. this._resizeX = this._resizeY = true;
  93. // FIXME: need logic to determine NW or NE class to
  94. // see
  95. // based on which [todo] corner is clicked
  96. dojo.addClass(this.resizeHandle, "dojoxResizeNW");
  97. break;
  98. case "x" :
  99. this._resizeX = true;
  100. dojo.addClass(this.resizeHandle, "dojoxResizeW");
  101. break;
  102. case "y" :
  103. this._resizeY = true;
  104. dojo.addClass(this.resizeHandle, "dojoxResizeN");
  105. break;
  106. }
  107. },
  108. _beginSizing : function(/* Event */e) {
  109. // summary: setup movement listeners and calculate initial
  110. // size
  111. if (this._isSizing) {
  112. return false;
  113. }
  114. this.targetWidget = dijit.byId(this.targetId);
  115. // FIXME: resizing widgets does weird things, disable
  116. // virtual resizing for now:
  117. if (this.targetWidget) {
  118. this.activeResize = true;
  119. }
  120. this.targetDomNode = this.targetWidget
  121. ? this.targetWidget.domNode
  122. : dojo.byId(this.targetId);
  123. if (this.targetContainer) {
  124. this.targetDomNode = this.targetContainer;
  125. }
  126. if (!this.targetDomNode) {
  127. return;
  128. }
  129. if (!this.activeResize) {
  130. this.targetDomNode.appendChild(this._activeResizeNode);
  131. dojo.fadeIn({
  132. node : this._activeResizeNode,
  133. duration : 120,
  134. beforeBegin : dojo.hitch(this, function() {
  135. this._activeResizeNode.style.display = '';
  136. })
  137. }).play();
  138. }
  139. this._isSizing = true;
  140. this.startPoint = {
  141. 'x' : e.clientX,
  142. 'y' : e.clientY
  143. };
  144. // FIXME: this is funky: marginBox adds height, contentBox
  145. // ignores padding (expected, but foo!)
  146. var mb = (this.targetWidget) ? dojo
  147. .marginBox(this.targetDomNode) : dojo
  148. .contentBox(this.targetDomNode);
  149. this.startSize = {
  150. 'w' : mb.w,
  151. 'h' : mb.h
  152. };
  153. this._connects = [];
  154. this._connects.push(dojo.connect(document, "onmousemove",
  155. this, "_updateSizing"));
  156. this._connects.push(dojo.connect(document, "onmouseup",
  157. this, "_endSizing"));
  158. e.preventDefault();
  159. },
  160. _updateSizing : function(/* Event */e) {
  161. // summary: called when moving the ResizeHandle ...
  162. // determines
  163. // new size based on settings/position and sets styles.
  164. if (this.activeResize) {
  165. this._changeSizing(e);
  166. } else {
  167. var tmp = this._getNewCoords(e);
  168. if (tmp === false) {
  169. return;
  170. }
  171. dojo.style(this._activeResizeNode, "width", tmp.width
  172. + "px");
  173. dojo.style(this._activeResizeNode, "height", tmp.height
  174. + "px");
  175. this._activeResizeNode.style.display = '';
  176. }
  177. },
  178. _getNewCoords : function(/* Event */e) {
  179. // On IE, if you move the mouse above/to the left of the
  180. // object being resized,
  181. // sometimes clientX/Y aren't set, apparently. Just ignore
  182. // the event.
  183. try {
  184. if (!e.clientX || !e.clientY) {
  185. return false;
  186. }
  187. } catch (e) {
  188. // sometimes you get an exception accessing above
  189. // fields...
  190. return false;
  191. }
  192. this._activeResizeLastEvent = e;
  193. var dx = this.startPoint.x - e.clientX;
  194. var dy = this.startPoint.y - e.clientY;
  195. var newW = (this._resizeX)
  196. ? this.startSize.w - dx
  197. : this.startSize.w;
  198. var newH = (this._resizeY)
  199. ? this.startSize.h - dy
  200. : this.startSize.h;
  201. // minimum size check
  202. if (this.minSize) {
  203. // var mb = dojo.marginBox(this.targetDomNode);
  204. if (newW < this.minSize.w) {
  205. newW = this.minSize.w;
  206. }
  207. if (newH < this.minSize.h) {
  208. newH = this.minSize.h;
  209. }
  210. }
  211. return {
  212. width : newW,
  213. height : newH
  214. }; // Object
  215. },
  216. _changeSizing : function(/* Event */e) {
  217. // summary: apply sizing information based on information in
  218. // (e) to attached node
  219. var tmp = this._getNewCoords(e);
  220. if (tmp === false) {
  221. return;
  222. }
  223. if (this.targetWidget
  224. && typeof this.targetWidget.resize == "function") {
  225. this.targetWidget.resize({
  226. w : tmp.width,
  227. h : tmp.height
  228. });
  229. } else {
  230. if (this.animateSizing) {
  231. var anim = dojo.fx[this.animateMethod]([
  232. dojo.animateProperty({
  233. node : this.targetDomNode,
  234. properties : {
  235. width : {
  236. start : this.startSize.w,
  237. end : tmp.width,
  238. unit : 'px'
  239. }
  240. },
  241. duration : this.animateDuration
  242. }), dojo.animateProperty({
  243. node : this.targetDomNode,
  244. properties : {
  245. height : {
  246. start : this.startSize.h,
  247. end : tmp.height,
  248. unit : 'px'
  249. }
  250. },
  251. duration : this.animateDuration
  252. })]);
  253. anim.play();
  254. } else {
  255. dojo.style(this.targetDomNode, "width", tmp.width
  256. + "px");
  257. dojo.style(this.targetDomNode, "height", tmp.height
  258. + "px");
  259. }
  260. }
  261. e.preventDefault();
  262. },
  263. _endSizing : function(/* Event */e) {
  264. // summary: disconnect listenrs and cleanup sizing
  265. dojo.forEach(this._connects, function(c) {
  266. dojo.disconnect(c);
  267. });
  268. if (!this.activeResize) {
  269. dojo.fadeOut({
  270. node : this._activeResizeNode,
  271. duration : 250,
  272. onEnd : dojo.hitch(this, function() {
  273. this._activeResizeNode.style.display = "none";
  274. })
  275. }).play();
  276. this._changeSizing(e);
  277. }
  278. this._isSizing = false;
  279. }
  280. });
  281. }