]> git.wh0rd.org Git - 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 });