]> git.wh0rd.org - tt-rss.git/blob - lib/dijit/layout/_ContentPaneResizeMixin.js.uncompressed.js
update dojo to 1.7.3
[tt-rss.git] / lib / dijit / layout / _ContentPaneResizeMixin.js.uncompressed.js
1 define("dijit/layout/_ContentPaneResizeMixin", [
2 "dojo/_base/array", // array.filter array.forEach
3 "dojo/_base/declare", // declare
4 "dojo/dom-attr", // domAttr.has
5 "dojo/dom-class", // domClass.contains domClass.toggle
6 "dojo/dom-geometry",// domGeometry.contentBox domGeometry.marginBox
7 "dojo/_base/lang", // lang.mixin
8 "dojo/query", // query
9 "dojo/_base/sniff", // has("ie")
10 "dojo/_base/window", // win.global
11 "../registry", // registry.byId
12 "./utils", // marginBox2contextBox
13 "../_Contained"
14 ], function(array, declare, domAttr, domClass, domGeometry, lang, query, has, win,
15 registry, layoutUtils, _Contained){
16
17 /*=====
18 var _Contained = dijit._Contained;
19 =====*/
20
21 // module:
22 // dijit/layout/_ContentPaneResizeMixin
23 // summary:
24 // Resize() functionality of ContentPane. If there's a single layout widget
25 // child then it will call resize() with the same dimensions as the ContentPane.
26 // Otherwise just calls resize on each child.
27
28
29 return declare("dijit.layout._ContentPaneResizeMixin", null, {
30 // summary:
31 // Resize() functionality of ContentPane. If there's a single layout widget
32 // child then it will call resize() with the same dimensions as the ContentPane.
33 // Otherwise just calls resize on each child.
34 //
35 // Also implements basic startup() functionality, where starting the parent
36 // will start the children
37
38 // doLayout: Boolean
39 // - false - don't adjust size of children
40 // - true - if there is a single visible child widget, set it's size to
41 // however big the ContentPane is
42 doLayout: true,
43
44 // isLayoutContainer: [protected] Boolean
45 // Indicates that this widget will call resize() on it's child widgets
46 // when they become visible.
47 isLayoutContainer: true,
48
49 startup: function(){
50 // summary:
51 // See `dijit.layout._LayoutWidget.startup` for description.
52 // Although ContentPane doesn't extend _LayoutWidget, it does implement
53 // the same API.
54
55 if(this._started){ return; }
56
57 var parent = this.getParent();
58 this._childOfLayoutWidget = parent && parent.isLayoutContainer;
59
60 // I need to call resize() on my child/children (when I become visible), unless
61 // I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
62 this._needLayout = !this._childOfLayoutWidget;
63
64 this.inherited(arguments);
65
66 if(this._isShown()){
67 this._onShow();
68 }
69
70 if(!this._childOfLayoutWidget){
71 // If my parent isn't a layout container, since my style *may be* width=height=100%
72 // or something similar (either set directly or via a CSS class),
73 // monitor when my size changes so that I can re-layout.
74 // For browsers where I can't directly monitor when my size changes,
75 // monitor when the viewport changes size, which *may* indicate a size change for me.
76 this.connect(has("ie") ? this.domNode : win.global, 'onresize', function(){
77 // Using function(){} closure to ensure no arguments to resize.
78 this._needLayout = !this._childOfLayoutWidget;
79 this.resize();
80 });
81 }
82 },
83
84 _checkIfSingleChild: function(){
85 // summary:
86 // Test if we have exactly one visible widget as a child,
87 // and if so assume that we are a container for that widget,
88 // and should propagate startup() and resize() calls to it.
89 // Skips over things like data stores since they aren't visible.
90
91 var childNodes = query("> *", this.containerNode).filter(function(node){
92 return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
93 }),
94 childWidgetNodes = childNodes.filter(function(node){
95 return domAttr.has(node, "data-dojo-type") || domAttr.has(node, "dojoType") || domAttr.has(node, "widgetId");
96 }),
97 candidateWidgets = array.filter(childWidgetNodes.map(registry.byNode), function(widget){
98 return widget && widget.domNode && widget.resize;
99 });
100
101 if(
102 // all child nodes are widgets
103 childNodes.length == childWidgetNodes.length &&
104
105 // all but one are invisible (like dojo.data)
106 candidateWidgets.length == 1
107 ){
108 this._singleChild = candidateWidgets[0];
109 }else{
110 delete this._singleChild;
111 }
112
113 // So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
114 domClass.toggle(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild);
115 },
116
117 resize: function(changeSize, resultSize){
118 // summary:
119 // See `dijit.layout._LayoutWidget.resize` for description.
120 // Although ContentPane doesn't extend _LayoutWidget, it does implement
121 // the same API.
122
123 // For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
124 // never called, so resize() is our trigger to do the initial href download (see [20099]).
125 // However, don't load href for closed TitlePanes.
126 if(!this._wasShown && this.open !== false){
127 this._onShow();
128 }
129
130 this._resizeCalled = true;
131
132 this._scheduleLayout(changeSize, resultSize);
133 },
134
135 _scheduleLayout: function(changeSize, resultSize){
136 // summary:
137 // Resize myself, and call resize() on each of my child layout widgets, either now
138 // (if I'm currently visible) or when I become visible
139 if(this._isShown()){
140 this._layout(changeSize, resultSize);
141 }else{
142 this._needLayout = true;
143 this._changeSize = changeSize;
144 this._resultSize = resultSize;
145 }
146 },
147
148 _layout: function(changeSize, resultSize){
149 // summary:
150 // Resize myself according to optional changeSize/resultSize parameters, like a layout widget.
151 // Also, since I am a Container widget, each of my children expects me to
152 // call resize() or layout() on them.
153 //
154 // Should be called on initialization and also whenever we get new content
155 // (from an href, or from set('content', ...))... but deferred until
156 // the ContentPane is visible
157
158 // Set margin box size, unless it wasn't specified, in which case use current size.
159 if(changeSize){
160 domGeometry.setMarginBox(this.domNode, changeSize);
161 }
162
163 // Compute content box size of containerNode in case we [later] need to size our single child.
164 var cn = this.containerNode;
165 if(cn === this.domNode){
166 // If changeSize or resultSize was passed to this method and this.containerNode ==
167 // this.domNode then we can compute the content-box size without querying the node,
168 // which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
169 var mb = resultSize || {};
170 lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
171 if(!("h" in mb) || !("w" in mb)){
172 mb = lang.mixin(domGeometry.getMarginBox(cn), mb); // just use domGeometry.setMarginBox() to fill in missing values
173 }
174 this._contentBox = layoutUtils.marginBox2contentBox(cn, mb);
175 }else{
176 this._contentBox = domGeometry.getContentBox(cn);
177 }
178
179 this._layoutChildren();
180
181 delete this._needLayout;
182 },
183
184 _layoutChildren: function(){
185 // Call _checkIfSingleChild() again in case app has manually mucked w/the content
186 // of the ContentPane (rather than changing it through the set("content", ...) API.
187 if(this.doLayout){
188 this._checkIfSingleChild();
189 }
190
191 if(this._singleChild && this._singleChild.resize){
192 var cb = this._contentBox || domGeometry.getContentBox(this.containerNode);
193
194 // note: if widget has padding this._contentBox will have l and t set,
195 // but don't pass them to resize() or it will doubly-offset the child
196 this._singleChild.resize({w: cb.w, h: cb.h});
197 }else{
198 // All my child widgets are independently sized (rather than matching my size),
199 // but I still need to call resize() on each child to make it layout.
200 array.forEach(this.getChildren(), function(widget){
201 if(widget.resize){
202 widget.resize();
203 }
204 });
205 }
206 },
207
208 _isShown: function(){
209 // summary:
210 // Returns true if the content is currently shown.
211 // description:
212 // If I am a child of a layout widget then it actually returns true if I've ever been visible,
213 // not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
214 // tree every call, and at least solves the performance problem on page load by deferring loading
215 // hidden ContentPanes until they are first shown
216
217 if(this._childOfLayoutWidget){
218 // If we are TitlePane, etc - we return that only *IF* we've been resized
219 if(this._resizeCalled && "open" in this){
220 return this.open;
221 }
222 return this._resizeCalled;
223 }else if("open" in this){
224 return this.open; // for TitlePane, etc.
225 }else{
226 var node = this.domNode, parent = this.domNode.parentNode;
227 return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !domClass.contains(node, "dijitHidden") &&
228 parent && parent.style && (parent.style.display != 'none');
229 }
230 },
231
232 _onShow: function(){
233 // summary:
234 // Called when the ContentPane is made visible
235 // description:
236 // For a plain ContentPane, this is called on initialization, from startup().
237 // If the ContentPane is a hidden pane of a TabContainer etc., then it's
238 // called whenever the pane is made visible.
239 //
240 // Does layout/resize of child widget(s)
241
242 if(this._needLayout){
243 // If a layout has been scheduled for when we become visible, do it now
244 this._layout(this._changeSize, this._resultSize);
245 }
246
247 this.inherited(arguments);
248
249 // Need to keep track of whether ContentPane has been shown (which is different than
250 // whether or not it's currently visible).
251 this._wasShown = true;
252 }
253 });
254
255 });