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