]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dijit/layout/utils", [ |
2 | "dojo/_base/array", // array.filter array.forEach | |
3 | "dojo/dom-class", // domClass.add domClass.remove | |
4 | "dojo/dom-geometry", // domGeometry.marginBox | |
5 | "dojo/dom-style", // domStyle.getComputedStyle | |
6 | "dojo/_base/lang", // lang.mixin | |
7 | "../main" // for exporting symbols to dijit, remove in 2.0 | |
8 | ], function(array, domClass, domGeometry, domStyle, lang, dijit){ | |
9 | ||
10 | // module: | |
11 | // dijit/layout/utils | |
12 | ||
13 | var layout = lang.getObject("layout", true, dijit); | |
14 | /*===== | |
15 | layout = { | |
16 | // summary: | |
17 | // marginBox2contentBox() and layoutChildren() | |
18 | }; | |
19 | =====*/ | |
20 | ||
21 | layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){ | |
22 | // summary: | |
23 | // Given the margin-box size of a node, return its content box size. | |
24 | // Functions like domGeometry.contentBox() but is more reliable since it doesn't have | |
25 | // to wait for the browser to compute sizes. | |
26 | var cs = domStyle.getComputedStyle(node); | |
27 | var me = domGeometry.getMarginExtents(node, cs); | |
28 | var pb = domGeometry.getPadBorderExtents(node, cs); | |
29 | return { | |
30 | l: domStyle.toPixelValue(node, cs.paddingLeft), | |
31 | t: domStyle.toPixelValue(node, cs.paddingTop), | |
32 | w: mb.w - (me.w + pb.w), | |
33 | h: mb.h - (me.h + pb.h) | |
34 | }; | |
35 | }; | |
36 | ||
37 | function capitalize(word){ | |
38 | return word.substring(0,1).toUpperCase() + word.substring(1); | |
39 | } | |
40 | ||
41 | function size(widget, dim){ | |
42 | // size the child | |
43 | var newSize = widget.resize ? widget.resize(dim) : domGeometry.setMarginBox(widget.domNode, dim); | |
44 | ||
45 | // record child's size | |
46 | if(newSize){ | |
47 | // if the child returned it's new size then use that | |
48 | lang.mixin(widget, newSize); | |
49 | }else{ | |
50 | // otherwise, call getMarginBox(), but favor our own numbers when we have them. | |
51 | // the browser lies sometimes | |
52 | lang.mixin(widget, domGeometry.getMarginBox(widget.domNode)); | |
53 | lang.mixin(widget, dim); | |
54 | } | |
55 | } | |
56 | ||
57 | layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children, | |
58 | /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){ | |
59 | // summary: | |
60 | // Layout a bunch of child dom nodes within a parent dom node | |
61 | // container: | |
62 | // parent node | |
63 | // dim: | |
64 | // {l, t, w, h} object specifying dimensions of container into which to place children | |
65 | // children: | |
66 | // An array of Widgets or at least objects containing: | |
67 | // | |
68 | // - domNode: pointer to DOM node to position | |
69 | // - region or layoutAlign: position to place DOM node | |
70 | // - resize(): (optional) method to set size of node | |
71 | // - id: (optional) Id of widgets, referenced from resize object, below. | |
72 | // changedRegionId: | |
73 | // If specified, the slider for the region with the specified id has been dragged, and thus | |
74 | // the region's height or width should be adjusted according to changedRegionSize | |
75 | // changedRegionSize: | |
76 | // See changedRegionId. | |
77 | ||
78 | // copy dim because we are going to modify it | |
79 | dim = lang.mixin({}, dim); | |
80 | ||
81 | domClass.add(container, "dijitLayoutContainer"); | |
82 | ||
83 | // Move "client" elements to the end of the array for layout. a11y dictates that the author | |
84 | // needs to be able to put them in the document in tab-order, but this algorithm requires that | |
85 | // client be last. TODO: move these lines to LayoutContainer? Unneeded other places I think. | |
86 | children = array.filter(children, function(item){ return item.region != "center" && item.layoutAlign != "client"; }) | |
87 | .concat(array.filter(children, function(item){ return item.region == "center" || item.layoutAlign == "client"; })); | |
88 | ||
89 | // set positions/sizes | |
90 | array.forEach(children, function(child){ | |
91 | var elm = child.domNode, | |
92 | pos = (child.region || child.layoutAlign); | |
93 | if(!pos){ | |
94 | throw new Error("No region setting for " + child.id) | |
95 | } | |
96 | ||
97 | // set elem to upper left corner of unused space; may move it later | |
98 | var elmStyle = elm.style; | |
99 | elmStyle.left = dim.l+"px"; | |
100 | elmStyle.top = dim.t+"px"; | |
101 | elmStyle.position = "absolute"; | |
102 | ||
103 | domClass.add(elm, "dijitAlign" + capitalize(pos)); | |
104 | ||
105 | // Size adjustments to make to this child widget | |
106 | var sizeSetting = {}; | |
107 | ||
108 | // Check for optional size adjustment due to splitter drag (height adjustment for top/bottom align | |
109 | // panes and width adjustment for left/right align panes. | |
110 | if(changedRegionId && changedRegionId == child.id){ | |
111 | sizeSetting[child.region == "top" || child.region == "bottom" ? "h" : "w"] = changedRegionSize; | |
112 | } | |
113 | ||
114 | // set size && adjust record of remaining space. | |
115 | // note that setting the width of a <div> may affect its height. | |
116 | if(pos == "top" || pos == "bottom"){ | |
117 | sizeSetting.w = dim.w; | |
118 | size(child, sizeSetting); | |
119 | dim.h -= child.h; | |
120 | if(pos == "top"){ | |
121 | dim.t += child.h; | |
122 | }else{ | |
123 | elmStyle.top = dim.t + dim.h + "px"; | |
124 | } | |
125 | }else if(pos == "left" || pos == "right"){ | |
126 | sizeSetting.h = dim.h; | |
127 | size(child, sizeSetting); | |
128 | dim.w -= child.w; | |
129 | if(pos == "left"){ | |
130 | dim.l += child.w; | |
131 | }else{ | |
132 | elmStyle.left = dim.l + dim.w + "px"; | |
133 | } | |
134 | }else if(pos == "client" || pos == "center"){ | |
135 | size(child, dim); | |
136 | } | |
137 | }); | |
138 | }; | |
139 | ||
140 | ||
141 | return { | |
142 | marginBox2contentBox: layout.marginBox2contentBox, | |
143 | layoutChildren: layout.layoutChildren | |
144 | }; | |
145 | }); |