_LayoutWidget.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. define("dijit/layout/_LayoutWidget", [
  2. "dojo/_base/lang", // lang.mixin
  3. "../_Widget",
  4. "../_Container",
  5. "../_Contained",
  6. "dojo/_base/declare", // declare
  7. "dojo/dom-class", // domClass.add domClass.remove
  8. "dojo/dom-geometry", // domGeometry.marginBox
  9. "dojo/dom-style", // domStyle.getComputedStyle
  10. "dojo/_base/sniff", // has("ie")
  11. "dojo/_base/window" // win.global
  12. ], function(lang, _Widget, _Container, _Contained,
  13. declare, domClass, domGeometry, domStyle, has, win){
  14. /*=====
  15. var _Widget = dijit._Widget;
  16. var _Container = dijit._Container;
  17. var _Contained = dijit._Contained;
  18. =====*/
  19. // module:
  20. // dijit/layout/_LayoutWidget
  21. // summary:
  22. // _LayoutWidget Base class for a _Container widget which is responsible for laying out its children.
  23. // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
  24. return declare("dijit.layout._LayoutWidget", [_Widget, _Container, _Contained], {
  25. // summary:
  26. // Base class for a _Container widget which is responsible for laying out its children.
  27. // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
  28. // baseClass: [protected extension] String
  29. // This class name is applied to the widget's domNode
  30. // and also may be used to generate names for sub nodes,
  31. // for example dijitTabContainer-content.
  32. baseClass: "dijitLayoutContainer",
  33. // isLayoutContainer: [protected] Boolean
  34. // Indicates that this widget is going to call resize() on its
  35. // children widgets, setting their size, when they become visible.
  36. isLayoutContainer: true,
  37. buildRendering: function(){
  38. this.inherited(arguments);
  39. domClass.add(this.domNode, "dijitContainer");
  40. },
  41. startup: function(){
  42. // summary:
  43. // Called after all the widgets have been instantiated and their
  44. // dom nodes have been inserted somewhere under win.doc.body.
  45. //
  46. // Widgets should override this method to do any initialization
  47. // dependent on other widgets existing, and then call
  48. // this superclass method to finish things off.
  49. //
  50. // startup() in subclasses shouldn't do anything
  51. // size related because the size of the widget hasn't been set yet.
  52. if(this._started){ return; }
  53. // Need to call inherited first - so that child widgets get started
  54. // up correctly
  55. this.inherited(arguments);
  56. // If I am a not being controlled by a parent layout widget...
  57. var parent = this.getParent && this.getParent();
  58. if(!(parent && parent.isLayoutContainer)){
  59. // Do recursive sizing and layout of all my descendants
  60. // (passing in no argument to resize means that it has to glean the size itself)
  61. this.resize();
  62. // Since my parent isn't a layout container, and my style *may be* width=height=100%
  63. // or something similar (either set directly or via a CSS class),
  64. // monitor when viewport size changes so that I can re-layout.
  65. this.connect(win.global, 'onresize', function(){
  66. // Using function(){} closure to ensure no arguments passed to resize().
  67. this.resize();
  68. });
  69. }
  70. },
  71. resize: function(changeSize, resultSize){
  72. // summary:
  73. // Call this to resize a widget, or after its size has changed.
  74. // description:
  75. // Change size mode:
  76. // When changeSize is specified, changes the marginBox of this widget
  77. // and forces it to relayout its contents accordingly.
  78. // changeSize may specify height, width, or both.
  79. //
  80. // If resultSize is specified it indicates the size the widget will
  81. // become after changeSize has been applied.
  82. //
  83. // Notification mode:
  84. // When changeSize is null, indicates that the caller has already changed
  85. // the size of the widget, or perhaps it changed because the browser
  86. // window was resized. Tells widget to relayout its contents accordingly.
  87. //
  88. // If resultSize is also specified it indicates the size the widget has
  89. // become.
  90. //
  91. // In either mode, this method also:
  92. // 1. Sets this._borderBox and this._contentBox to the new size of
  93. // the widget. Queries the current domNode size if necessary.
  94. // 2. Calls layout() to resize contents (and maybe adjust child widgets).
  95. //
  96. // changeSize: Object?
  97. // Sets the widget to this margin-box size and position.
  98. // May include any/all of the following properties:
  99. // | {w: int, h: int, l: int, t: int}
  100. //
  101. // resultSize: Object?
  102. // The margin-box size of this widget after applying changeSize (if
  103. // changeSize is specified). If caller knows this size and
  104. // passes it in, we don't need to query the browser to get the size.
  105. // | {w: int, h: int}
  106. var node = this.domNode;
  107. // set margin box size, unless it wasn't specified, in which case use current size
  108. if(changeSize){
  109. domGeometry.setMarginBox(node, changeSize);
  110. }
  111. // If either height or width wasn't specified by the user, then query node for it.
  112. // But note that setting the margin box and then immediately querying dimensions may return
  113. // inaccurate results, so try not to depend on it.
  114. var mb = resultSize || {};
  115. lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
  116. if( !("h" in mb) || !("w" in mb) ){
  117. mb = lang.mixin(domGeometry.getMarginBox(node), mb); // just use domGeometry.marginBox() to fill in missing values
  118. }
  119. // Compute and save the size of my border box and content box
  120. // (w/out calling domGeometry.getContentBox() since that may fail if size was recently set)
  121. var cs = domStyle.getComputedStyle(node);
  122. var me = domGeometry.getMarginExtents(node, cs);
  123. var be = domGeometry.getBorderExtents(node, cs);
  124. var bb = (this._borderBox = {
  125. w: mb.w - (me.w + be.w),
  126. h: mb.h - (me.h + be.h)
  127. });
  128. var pe = domGeometry.getPadExtents(node, cs);
  129. this._contentBox = {
  130. l: domStyle.toPixelValue(node, cs.paddingLeft),
  131. t: domStyle.toPixelValue(node, cs.paddingTop),
  132. w: bb.w - pe.w,
  133. h: bb.h - pe.h
  134. };
  135. // Callback for widget to adjust size of its children
  136. this.layout();
  137. },
  138. layout: function(){
  139. // summary:
  140. // Widgets override this method to size and position their contents/children.
  141. // When this is called this._contentBox is guaranteed to be set (see resize()).
  142. //
  143. // This is called after startup(), and also when the widget's size has been
  144. // changed.
  145. // tags:
  146. // protected extension
  147. },
  148. _setupChild: function(/*dijit._Widget*/child){
  149. // summary:
  150. // Common setup for initial children and children which are added after startup
  151. // tags:
  152. // protected extension
  153. var cls = this.baseClass + "-child "
  154. + (child.baseClass ? this.baseClass + "-" + child.baseClass : "");
  155. domClass.add(child.domNode, cls);
  156. },
  157. addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
  158. // Overrides _Container.addChild() to call _setupChild()
  159. this.inherited(arguments);
  160. if(this._started){
  161. this._setupChild(child);
  162. }
  163. },
  164. removeChild: function(/*dijit._Widget*/ child){
  165. // Overrides _Container.removeChild() to remove class added by _setupChild()
  166. var cls = this.baseClass + "-child"
  167. + (child.baseClass ?
  168. " " + this.baseClass + "-" + child.baseClass : "");
  169. domClass.remove(child.domNode, cls);
  170. this.inherited(arguments);
  171. }
  172. });
  173. });