One vertical scroll bar for whole Dijit BorderContainer

1.1k views Asked by At

Here is the structure of my HTML body.

 <body class="claro">
<div id="BorderContainerMain" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'headline'" style="width: 100%; border:0; padding:0; margin:0;">
    <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'" style="border: 0;">
        <div id="topBanner" data-dojo-type="core.widget.GeneralMainHeader" ></div>
    </div>
    <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'left'" style="border: 0;">
        <div id="leftNav" data-dojo-type="core.widget.GeneralLeftNavigation"></div>
    </div>
    <div id="contentStackContainer" data-dojo-type="dijit.layout.StackContainer" data-dojo-props="region:'center', style: 'border: 0; padding: 0; margin: 0;'"></div>
</div>

Now, my desire is to make the whole screen auto grow in height depending on the content of the center region and let the viewport handle the vertical scrolling. I am fairly new into dijit layout and I am using DOJO 1.6. I have already learned that I have to write code to achieve this. So, I am trying to get some experience guidance on this.

Thanks, Rishi

So, I wrote up a custom resize for my purpose but it is not working. Is there any why it not working. Here is the code:

dojo.provide("core.widget.ClientBorderContainer");
dojo.require("dijit.layout.BorderContainer");
dojo.declare("core.widget.ClientBorderContainer", [dijit.layout.BorderContainer], {

totalHeight: 0,

_setupChild: function(/*dijit._Widget*/ child){
    // Override BorderContainer._setupChild().

    var region = child.region;
    console.debug("region :: "+region);
    if(region){
        this.inherited(arguments);

        dojo.addClass(child.domNode, this.baseClass+"Pane");

        var ltr = this.isLeftToRight();
        if(region == "leading"){ region = ltr ? "left" : "right"; }
        if(region == "trailing"){ region = ltr ? "right" : "left"; }

        // Create draggable splitter for resizing pane,
        // or alternately if splitter=false but BorderContainer.gutters=true then
        // insert dummy div just for spacing
        if(region != "center" && (child.splitter || this.gutters) && !child._splitterWidget){
            var _Splitter = dojo.getObject(child.splitter ? this._splitterClass : "dijit.layout._Gutter");
            var splitter = new _Splitter({
                id: child.id + "_splitter",
                container: this,
                child: child,
                region: region,
                live: this.liveSplitters
            });
            splitter.isSplitter = true;
            child._splitterWidget = splitter;

            dojo.place(splitter.domNode, child.domNode, "after");

            // Splitters aren't added as Contained children, so we need to call startup explicitly
            splitter.startup();
            console.debug("Should not be printed as there is no splitter");
        }
        child.region = region;  // TODO: technically wrong since it overwrites "trailing" with "left" etc.
    }
},

resize: function(newSize, currentSize){
    // Overrides BorderContainer.resize().

    // resetting potential padding to 0px to provide support for 100% width/height + padding
    // TODO: this hack doesn't respect the box model and is a temporary fix
    if(!this.cs || !this.pe){
        var node = this.domNode;
        this.cs = dojo.getComputedStyle(node);
        this.pe = dojo._getPadExtents(node, this.cs);
        this.pe.r = dojo._toPixelValue(node, this.cs.paddingRight);
        this.pe.b = dojo._toPixelValue(node, this.cs.paddingBottom);

        dojo.style(node, "padding", "0px");
    }

    //Following section calculates the desired height of the BorderContainer
    console.debug(this.id+" contentBox height ::: "+dojo.contentBox(this.domNode).h);
    this.totalHeight = 0;
    dojo.forEach(this.getChildren(), this.calculateHeight, this);
    console.debug("this.totalHeight ::: "+this.totalHeight);
    console.debug("newSize "+newSize);
    console.debug("currentSize "+currentSize);

    ////////////////////////////////////////////////
    // summary:
    //      Call this to resize a widget, or after its size has changed.
    // description:
    //      Change size mode:
    //          When changeSize is specified, changes the marginBox of this widget
    //          and forces it to relayout its contents accordingly.
    //          changeSize may specify height, width, or both.
    //
    //          If resultSize is specified it indicates the size the widget will
    //          become after changeSize has been applied.
    //
    //      Notification mode:
    //          When changeSize is null, indicates that the caller has already changed
    //          the size of the widget, or perhaps it changed because the browser
    //          window was resized.  Tells widget to relayout its contents accordingly.
    //
    //          If resultSize is also specified it indicates the size the widget has
    //          become.
    //
    //      In either mode, this method also:
    //          1. Sets this._borderBox and this._contentBox to the new size of
    //              the widget.  Queries the current domNode size if necessary.
    //          2. Calls layout() to resize contents (and maybe adjust child widgets).
    //
    // changeSize: Object?
    //      Sets the widget to this margin-box size and position.
    //      May include any/all of the following properties:
    //  |   {w: int, h: int, l: int, t: int}
    //
    // resultSize: Object?
    //      The margin-box size of this widget after applying changeSize (if
    //      changeSize is specified).  If caller knows this size and
    //      passes it in, we don't need to query the browser to get the size.
    //  |   {w: int, h: int}

    var node = this.domNode;

    // set margin box size, unless it wasn't specified, in which case use current size
    if(newSize){
        dojo.marginBox(node, newSize);

        // set offset of the node
        if(newSize.t){ node.style.top = newSize.t + "px"; }
        if(newSize.l){ node.style.left = newSize.l + "px"; }
    }

    // If either height or width wasn't specified by the user, then query node for it.
    // But note that setting the margin box and then immediately querying dimensions may return
    // inaccurate results, so try not to depend on it.
    var mb = currentSize || {};
    dojo.mixin(mb, {h: this.totalHeight}); // calculated height overrides currentSize
    if( !("h" in mb) || !("w" in mb) ){
        mb = dojo.mixin(dojo.marginBox(node), mb);  // just use dojo.marginBox() to fill in missing values
    }
    // Compute and save the size of my border box and content box
    // (w/out calling dojo.contentBox() since that may fail if size was recently set)
    var cs = dojo.getComputedStyle(node);
    var me = dojo._getMarginExtents(node, cs);
    var be = dojo._getBorderExtents(node, cs);
    console.debug("mb.w "+mb.w);
    console.debug("mb.h "+mb.h);
    var bb = (this._borderBox = {
        w: mb.w - (me.w + be.w),
        h: mb.h - (me.h + be.h)
    });
    var pe = dojo._getPadExtents(node, cs);
    console.debug("bb.w "+bb.w);
    console.debug("bb.h "+bb.h);
    this._contentBox = {
        l: dojo._toPixelValue(node, cs.paddingLeft),
        t: dojo._toPixelValue(node, cs.paddingTop),
        w: bb.w - pe.w,
        h: bb.h - pe.h
    };
    // Callback for widget to adjust size of its children
    this.layout();
    ///////////////////////////////////////////////
    console.debug(this.id+" contentBox height ::: "+dojo.contentBox(this.domNode).h);
},

calculateHeight: function(/*dijit._Widget*/ child){
    var region = child.region;
    console.debug("region :: "+region);
    if(region && (region == "top" || region == "center" || region == "bottom")){
        var childHeight = 0;
        if(child instanceof dijit.layout.StackContainer){
            console.debug("selectedChildWidget "+child.selectedChildWidget);
            if(child.selectedChildWidget)
                childHeight = dojo.contentBox(child.selectedChildWidget.domNode).h;
            else
                childHeight = dojo.contentBox(child.domNode).h;
        }else{
            childHeight = dojo.contentBox(child.domNode).h;
        }
        this.totalHeight = this.totalHeight+childHeight;
        console.debug("childHeight = "+childHeight+" child.declaredClass"+child.declaredClass);
    }
},

_layoutChildren: function(/*String?*/ changedChildId, /*Number?*/ changedChildSize){
    // summary:
    //      This is the main routine for setting size/position of each child.
    // description:
    //      With no arguments, measures the height of top/bottom panes, the width
    //      of left/right panes, and then sizes all panes accordingly.
    //
    //      With changedRegion specified (as "left", "top", "bottom", or "right"),
    //      it changes that region's width/height to changedRegionSize and
    //      then resizes other regions that were affected.
    // changedChildId:
    //      Id of the child which should be resized because splitter was dragged.
    // changedChildSize:
    //      The new width/height (in pixels) to make specified child

    if(!this._borderBox || !this._borderBox.h){
        // We are currently hidden, or we haven't been sized by our parent yet.
        // Abort.   Someone will resize us later.
        return;
    }
    console.debug("custom lay out children called");
    // Generate list of wrappers of my children in the order that I want layoutChildren()
    // to process them (i.e. from the outside to the inside)
    var wrappers = dojo.map(this.getChildren(), function(child, idx){
        return {
            pane: child,
            weight: [
                child.region == "center" ? Infinity : 0,
                child.layoutPriority,
                (this.design == "sidebar" ? 1 : -1) * (/top|bottom/.test(child.region) ? 1 : -1),
                idx
            ]
        };
    }, this);
    wrappers.sort(function(a, b){
        var aw = a.weight, bw = b.weight;
        for(var i=0; i<aw.length; i++){
            if(aw[i] != bw[i]){
                return aw[i] - bw[i];
            }
        }
        return 0;
    });

    // Make new list, combining the externally specified children with splitters and gutters
    var childrenAndSplitters = [];
    dojo.forEach(wrappers, function(wrapper){
        var pane = wrapper.pane;
        childrenAndSplitters.push(pane);
        if(pane._splitterWidget){
            childrenAndSplitters.push(pane._splitterWidget);
        }
    });

    // Compute the box in which to lay out my children
    console.debug("this._borderBox.h :: "+this._borderBox.h);
    var dim = {
        l: this.pe.l,
        t: this.pe.t,
        w: this._borderBox.w - this.pe.w,
        h: this._borderBox.h - this.pe.h
    };

    // Layout the children, possibly changing size due to a splitter drag
    dijit.layout.layoutChildren(this.domNode, dim, childrenAndSplitters,
        changedChildId, changedChildSize);
}    
});
1

There are 1 answers

2
peller On

BorderContainer was written to take a sized box and calculate the center based on what's left over, sort of the opposite of what you're trying to do. AFAIK it won't support this.