_LayoutWidget.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. if (!dojo._hasResource["dijit.layout._LayoutWidget"]) { // _hasResource checks
  2. // added by build. Do
  3. // not use _hasResource
  4. // directly in your
  5. // code.
  6. dojo._hasResource["dijit.layout._LayoutWidget"] = true;
  7. dojo.provide("dijit.layout._LayoutWidget");
  8. dojo.require("dijit._Widget");
  9. dojo.require("dijit._Container");
  10. dojo.declare("dijit.layout._LayoutWidget", [dijit._Widget,
  11. dijit._Container, dijit._Contained], {
  12. // summary
  13. // Mixin for widgets that contain a list of children like
  14. // SplitContainer.
  15. // Widgets which mixin this code must define layout() to lay out
  16. // the children
  17. isLayoutContainer : true,
  18. postCreate : function() {
  19. dojo.addClass(this.domNode, "dijitContainer");
  20. },
  21. startup : function() {
  22. // summary:
  23. // Called after all the widgets have been instantiated and
  24. // their
  25. // dom nodes have been inserted somewhere under
  26. // document.body.
  27. //
  28. // Widgets should override this method to do any
  29. // initialization
  30. // dependent on other widgets existing, and then call
  31. // this superclass method to finish things off.
  32. //
  33. // startup() in subclasses shouldn't do anything
  34. // size related because the size of the widget hasn't been
  35. // set yet.
  36. if (this._started) {
  37. return;
  38. }
  39. this._started = true;
  40. if (this.getChildren) {
  41. dojo.forEach(this.getChildren(), function(child) {
  42. child.startup();
  43. });
  44. }
  45. // If I am a top level widget
  46. if (!this.getParent || !this.getParent()) {
  47. // Do recursive sizing and layout of all my descendants
  48. // (passing in no argument to resize means that it has
  49. // to glean the size itself)
  50. this.resize();
  51. // since my parent isn't a layout container, and my
  52. // style is width=height=100% (or something similar),
  53. // then I need to watch when the window resizes, and
  54. // size myself accordingly
  55. // (passing in no argument to resize means that it has
  56. // to glean the size itself)
  57. this.connect(window, 'onresize', function() {
  58. this.resize();
  59. });
  60. }
  61. },
  62. resize : function(args) {
  63. // summary:
  64. // Explicitly set this widget's size (in pixels),
  65. // and then call layout() to resize contents (and maybe
  66. // adjust child widgets)
  67. //
  68. // args: Object?
  69. // {w: int, h: int, l: int, t: int}
  70. var node = this.domNode;
  71. // set margin box size, unless it wasn't specified, in which
  72. // case use current size
  73. if (args) {
  74. dojo.marginBox(node, args);
  75. // set offset of the node
  76. if (args.t) {
  77. node.style.top = args.t + "px";
  78. }
  79. if (args.l) {
  80. node.style.left = args.l + "px";
  81. }
  82. }
  83. // If either height or width wasn't specified by the user,
  84. // then query node for it.
  85. // But note that setting the margin box and then immediately
  86. // querying dimensions may return
  87. // inaccurate results, so try not to depend on it.
  88. var mb = dojo.mixin(dojo.marginBox(node), args || {});
  89. // Save the size of my content box.
  90. this._contentBox = dijit.layout.marginBox2contentBox(node,
  91. mb);
  92. // Callback for widget to adjust size of it's children
  93. this.layout();
  94. },
  95. layout : function() {
  96. // summary
  97. // Widgets override this method to size & position their
  98. // contents/children.
  99. // When this is called this._contentBox is guaranteed to be
  100. // set (see resize()).
  101. //
  102. // This is called after startup(), and also when the
  103. // widget's size has been
  104. // changed.
  105. }
  106. });
  107. dijit.layout.marginBox2contentBox = function(/* DomNode */node, /* Object */
  108. mb) {
  109. // summary:
  110. // Given the margin-box size of a node, return it's content box size.
  111. // Functions like dojo.contentBox() but is more reliable since it
  112. // doesn't have
  113. // to wait for the browser to compute sizes.
  114. var cs = dojo.getComputedStyle(node);
  115. var me = dojo._getMarginExtents(node, cs);
  116. var pb = dojo._getPadBorderExtents(node, cs);
  117. return {
  118. l : dojo._toPixelValue(node, cs.paddingLeft),
  119. t : dojo._toPixelValue(node, cs.paddingTop),
  120. w : mb.w - (me.w + pb.w),
  121. h : mb.h - (me.h + pb.h)
  122. };
  123. };
  124. (function() {
  125. var capitalize = function(word) {
  126. return word.substring(0, 1).toUpperCase() + word.substring(1);
  127. };
  128. var size = function(widget, dim) {
  129. // size the child
  130. widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode,
  131. dim);
  132. // record child's size, but favor our own numbers when we have them.
  133. // the browser lies sometimes
  134. dojo.mixin(widget, dojo.marginBox(widget.domNode));
  135. dojo.mixin(widget, dim);
  136. };
  137. dijit.layout.layoutChildren = function(/* DomNode */container, /* Object */
  138. dim, /* Object[] */children) {
  139. /**
  140. * summary Layout a bunch of child dom nodes within a parent dom
  141. * node container: parent node dim: {l, t, w, h} object specifying
  142. * dimensions of container into which to place children children: an
  143. * array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode:
  144. * bar, layoutAlign: "client"} ]
  145. */
  146. // copy dim because we are going to modify it
  147. dim = dojo.mixin({}, dim);
  148. dojo.addClass(container, "dijitLayoutContainer");
  149. // Move "client" elements to the end of the array for layout. a11y
  150. // dictates that the author
  151. // needs to be able to put them in the document in tab-order, but
  152. // this algorithm requires that
  153. // client be last.
  154. children = dojo.filter(children, function(item) {
  155. return item.layoutAlign != "client";
  156. }).concat(dojo.filter(children, function(item) {
  157. return item.layoutAlign == "client";
  158. }));
  159. // set positions/sizes
  160. dojo.forEach(children, function(child) {
  161. var elm = child.domNode, pos = child.layoutAlign;
  162. // set elem to upper left corner of unused space; may
  163. // move it later
  164. var elmStyle = elm.style;
  165. elmStyle.left = dim.l + "px";
  166. elmStyle.top = dim.t + "px";
  167. elmStyle.bottom = elmStyle.right = "auto";
  168. dojo.addClass(elm, "dijitAlign" + capitalize(pos));
  169. // set size && adjust record of remaining space.
  170. // note that setting the width of a <div> may affect
  171. // it's height.
  172. if (pos == "top" || pos == "bottom") {
  173. size(child, {
  174. w : dim.w
  175. });
  176. dim.h -= child.h;
  177. if (pos == "top") {
  178. dim.t += child.h;
  179. } else {
  180. elmStyle.top = dim.t + dim.h + "px";
  181. }
  182. } else if (pos == "left" || pos == "right") {
  183. size(child, {
  184. h : dim.h
  185. });
  186. dim.w -= child.w;
  187. if (pos == "left") {
  188. dim.l += child.w;
  189. } else {
  190. elmStyle.left = dim.l + dim.w + "px";
  191. }
  192. } else if (pos == "client") {
  193. size(child, dim);
  194. }
  195. });
  196. };
  197. })();
  198. }