[483] | 1 | define([ |
---|
| 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, lang.setObject |
---|
| 7 | ], function(array, domClass, domGeometry, domStyle, lang){ |
---|
| 8 | |
---|
| 9 | // module: |
---|
| 10 | // dijit/layout/utils |
---|
| 11 | |
---|
| 12 | function capitalize(word){ |
---|
| 13 | return word.substring(0,1).toUpperCase() + word.substring(1); |
---|
| 14 | } |
---|
| 15 | |
---|
| 16 | function size(widget, dim){ |
---|
| 17 | // size the child |
---|
| 18 | var newSize = widget.resize ? widget.resize(dim) : domGeometry.setMarginBox(widget.domNode, dim); |
---|
| 19 | |
---|
| 20 | // record child's size |
---|
| 21 | if(newSize){ |
---|
| 22 | // if the child returned it's new size then use that |
---|
| 23 | lang.mixin(widget, newSize); |
---|
| 24 | }else{ |
---|
| 25 | // otherwise, call getMarginBox(), but favor our own numbers when we have them. |
---|
| 26 | // the browser lies sometimes |
---|
| 27 | lang.mixin(widget, domGeometry.getMarginBox(widget.domNode)); |
---|
| 28 | lang.mixin(widget, dim); |
---|
| 29 | } |
---|
| 30 | } |
---|
| 31 | |
---|
| 32 | var utils = { |
---|
| 33 | // summary: |
---|
| 34 | // Utility functions for doing layout |
---|
| 35 | |
---|
| 36 | marginBox2contentBox: function(/*DomNode*/ node, /*Object*/ mb){ |
---|
| 37 | // summary: |
---|
| 38 | // Given the margin-box size of a node, return its content box size. |
---|
| 39 | // Functions like domGeometry.contentBox() but is more reliable since it doesn't have |
---|
| 40 | // to wait for the browser to compute sizes. |
---|
| 41 | var cs = domStyle.getComputedStyle(node); |
---|
| 42 | var me = domGeometry.getMarginExtents(node, cs); |
---|
| 43 | var pb = domGeometry.getPadBorderExtents(node, cs); |
---|
| 44 | return { |
---|
| 45 | l: domStyle.toPixelValue(node, cs.paddingLeft), |
---|
| 46 | t: domStyle.toPixelValue(node, cs.paddingTop), |
---|
| 47 | w: mb.w - (me.w + pb.w), |
---|
| 48 | h: mb.h - (me.h + pb.h) |
---|
| 49 | }; |
---|
| 50 | }, |
---|
| 51 | |
---|
| 52 | |
---|
| 53 | layoutChildren: function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children, |
---|
| 54 | /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){ |
---|
| 55 | // summary: |
---|
| 56 | // Layout a bunch of child dom nodes within a parent dom node |
---|
| 57 | // container: |
---|
| 58 | // parent node |
---|
| 59 | // dim: |
---|
| 60 | // {l, t, w, h} object specifying dimensions of container into which to place children |
---|
| 61 | // children: |
---|
| 62 | // An array of Widgets or at least objects containing: |
---|
| 63 | // |
---|
| 64 | // - domNode: pointer to DOM node to position |
---|
| 65 | // - region or layoutAlign: position to place DOM node |
---|
| 66 | // - resize(): (optional) method to set size of node |
---|
| 67 | // - id: (optional) Id of widgets, referenced from resize object, below. |
---|
| 68 | // |
---|
| 69 | // The widgets in this array should be ordered according to how they should be laid out |
---|
| 70 | // (each element will be processed in order, and take up as much remaining space as needed), |
---|
| 71 | // with the center widget last. |
---|
| 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: remove for 2.0, all dijit client code already sends children as last item. |
---|
| 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 | if(pos == "leading"){ |
---|
| 115 | pos = child.isLeftToRight() ? "left" : "right"; |
---|
| 116 | } |
---|
| 117 | if(pos == "trailing"){ |
---|
| 118 | pos = child.isLeftToRight() ? "right" : "left"; |
---|
| 119 | } |
---|
| 120 | |
---|
| 121 | // set size && adjust record of remaining space. |
---|
| 122 | // note that setting the width of a <div> may affect its height. |
---|
| 123 | if(pos == "top" || pos == "bottom"){ |
---|
| 124 | sizeSetting.w = dim.w; |
---|
| 125 | size(child, sizeSetting); |
---|
| 126 | dim.h -= child.h; |
---|
| 127 | if(pos == "top"){ |
---|
| 128 | dim.t += child.h; |
---|
| 129 | }else{ |
---|
| 130 | elmStyle.top = dim.t + dim.h + "px"; |
---|
| 131 | } |
---|
| 132 | }else if(pos == "left" || pos == "right"){ |
---|
| 133 | sizeSetting.h = dim.h; |
---|
| 134 | size(child, sizeSetting); |
---|
| 135 | dim.w -= child.w; |
---|
| 136 | if(pos == "left"){ |
---|
| 137 | dim.l += child.w; |
---|
| 138 | }else{ |
---|
| 139 | elmStyle.left = dim.l + dim.w + "px"; |
---|
| 140 | } |
---|
| 141 | }else if(pos == "client" || pos == "center"){ |
---|
| 142 | size(child, dim); |
---|
| 143 | } |
---|
| 144 | }); |
---|
| 145 | } |
---|
| 146 | }; |
---|
| 147 | |
---|
| 148 | lang.setObject("dijit.layout.utils", utils); // remove for 2.0 |
---|
| 149 | |
---|
| 150 | return utils; |
---|
| 151 | }); |
---|