utils.js 4.9 KB

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