1. #11
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,507
    Vote Rating
    56
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Bump!

    Someone was (or should have been!) looking for this thread!

  2. #12
    Ext User
    Join Date
    Apr 2007
    Posts
    18
    Vote Rating
    0
    mangrar is on a distinguished road

      0  

    Post Maybe this class would be what I've been looking for

    Maybe this class would be what I've been looking for


    Hi,

    Maybe this class is what I'm looking for. I want to do the same that the portal example but disposing panels in rows instead of columns. Read this thread:

    http://extjs.com/forum/showthread.php?t=21215

    Bye.

  3. #13
    Sencha Premium Member
    Join Date
    Sep 2007
    Posts
    23
    Vote Rating
    1
    rkrishna_1975 is on a distinguished road

      0  

    Default


    Wow great work. I was looking for something similar to this myself.
    Ramki

  4. #14
    Ext User
    Join Date
    Apr 2007
    Posts
    18
    Vote Rating
    0
    mangrar is on a distinguished road

      0  

    Question It's half what I need

    It's half what I need


    Yesterday, I tested this new layout. I added three panels and each one fills a row. But this is half what I need. I need a row-layout, that's fine. The next step is a new layout, one like the horizontal panel in GWT library, to be used in each row. I need drag&drop panels to a row to be positioned horizontally in the row. See the Portal example of Ext2. I need the same application but in rows. So in the first row you can add 3 panels, each one with the same height but with different width.

    I've been thinking about creating a new layout using anchor layout philosophy. This layout, displays panels using HTML positioning. So, the second panel you add goes below the first one you added previously. This is what I need but in horizontal. So, when you add a new panel in a row of an row-layout, goes at the right of the previous one.

    Can someone give me some advice?

    Thanks a lot.

  5. #15
    Ext User
    Join Date
    Nov 2007
    Posts
    110
    Vote Rating
    0
    ray007 is on a distinguished road

      0  

    Talking


    Thanks for sharing your work, I've tried to improve a bit on it and extended it to automatically add the needed sliders and splitbars. Just add a property 'split' to the items to be resizable.

    Here we go:
    Code:
    Ext.namespace('Ext.ux.layout'); 
     
    /** 
     * @class Ext.ux.layout.RowFitLayout 
     * @extends Ext.layout.ContainerLayout 
     * <p>Layout that distributes heights of elements so they take 100% of the 
     * container height.</p> 
     * <p>Height of the child element can be given in pixels (as an integer) or 
     * in percent. All elements with absolute height (i.e. in pixels) always will 
     * have the given height. All "free" space (that is not filled with elements 
     * with 'absolute' height) will be distributed among other elements in 
     * proportion of their height percentage. Elements without 'height' in the 
     * config will take equal portions of the "unallocated" height.</p> 
     * <p>Supports panel collapsing, hiding, removal/addition. The adapter is provided 
     * to use with Ext.SplitBar: <b>Ext.ux.layout.RowFitLayout.SplitAdapter</b>.</p> 
     * <p>Example usage:</p> 
     * <pre><code> 
     var vp = new Ext.Viewport({ 
       layout: 'row-fit', 
       items: [ 
         { xtype: 'panel', height: 100, title: 'Height in pixels', html: 'panel height = 100px' }, 
         { xtype: 'panel', height: "50%", title: '1/2', html: 'Will take half of remaining height' }, 
         { xtype: 'panel', title: 'No height 1', html: 'Panel without given height', id: '' }, 
         { xtype: 'panel', title: 'No height 2', html: 'Another panel' } 
       ] 
     }); 
     * </code></pre> 
     * Usage of the split bar adapter: 
     * <pre><code> 
     var split = new Ext.SplitBar("elementToDrag", "elementToSize", Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP); 
     // note the Ext.SplitBar object is passed to the adapter constructor to set 
     // correct minSize and maxSize: 
     split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split)); 
     * </code></pre> 
     */ 
     
    Ext.ux.layout.RowFitLayout = Ext.extend(Ext.layout.ContainerLayout, {
      // private
      monitorResize: true,
    
      // private
      trackChildEvents: ['collapse', 'expand', 'hide', 'show'],
    
      // private
      splitHeight: 5,
      rendered: false,
    
      // private
      renderItem: function(c, position, target) {
        Ext.ux.layout.RowFitLayout.superclass.renderItem.apply(this, arguments);
    
        // add event listeners
        for (var i=0, n = this.trackChildEvents.length; i < n; i++) {
          var ev = this.trackChildEvents[i];
          //c.on(this.trackChildEvents[i], this.itemListener, this);
          c.on(ev, this['_item_' + ev], this);
        }
        c.animCollapse = false; // looks ugly together with row-fit layout
    
        this.checkRelHeight(c);
      },
    
      checkRelHeight: function(c) {
    
        // store some layout-specific calculations
        if(!c.rowFit) c.rowFit = {
          hasAbsHeight: false, // whether the component has absolute height (in pixels)
          relHeight: 0, // relative height, in pixels (if applicable)
          calcRelHeight: 0, // calculated relative height (used when element is resized)
          calcAbsHeight: 0, // calculated absolute height
          height: c.height  // save height config
        };
    
        // process height config option
        if (c.height) {
          var height = c.rowFit.height || c.height;
          // store relative (given in percent) height
          if (typeof height == "string" && height.indexOf("%")) {
            c.rowFit.relHeight = parseInt(height);
          }
          else { // set absolute height
            c.setHeight(c.height);
            //c.rowFit.hasAbsHeight = true;
            c.rowFit.hasAbsHeight = !Boolean(c.split);
          }
        }
        //if(c.split) c.rowFit.hasAbsHeight = false;
        c.isResizable = c.isResizable || Boolean(c.split) || !c.rowFit.hasAbsHeight;
      },
    
      // private
      onLayout: function(ct, target) {
    
        Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this, ct, target);
    
        if (this.container.collapsed || !ct.items || !ct.items.length) {
          return;
        }
    
        // first loop: determine how many elements with relative height are there,
        // sums of absolute and relative heights etc.
        var absHeightSum = 0, // sum of elements' absolute heights
            relHeightSum = 0, // sum of all percent heights given in children configs
            relHeightRatio = 1, // "scale" ratio used in case sum <> 100%
            noHeightCount = 0, // number of elements with no height given
            relHeightElements = []; // array of elements with 'relative' height for the second loop
    
        for (var i=0, n = ct.items.length; i < n; i++) {
          var c = ct.items.itemAt(i);
    
          if (!c.isVisible()) { continue; }
    
          // collapsed panel is treated as an element with absolute height
          if (c.collapsed) {
            absHeightSum += c.getFrameHeight();
          }
          else if (c.rowFit.hasAbsHeight) { // element that has an absolute height
            absHeightSum += c.height;
          }
          else { // 'relative-heighted'
            if (!c.rowFit.relHeight) { // element with no height given
              noHeightCount++;
            }
            else {
              relHeightSum += c.rowFit.relHeight;
            }
            relHeightElements.push(c);
          }
        }
    
        // if sum of relative heights <> 100% (e.g. error in config or consequence
        // of collapsing/removing panels), scale 'em so it becomes 100%
        if (noHeightCount == 0 && relHeightSum != 100) {
          relHeightRatio = 100 / relHeightSum;
        }
    
        var freeHeight = target.getStyleSize().height - absHeightSum, // "unallocated" height we have
            absHeightLeft = freeHeight; // track how much free space we have
    
        while (relHeightElements.length) {
          var c = relHeightElements.shift(), // element we're working with
              relH = c.rowFit.relHeight * relHeightRatio, // height of this element in percent
              absH = 0; // height in pixels
    
          // no height in config
          if (!relH) {
            relH = (100 - relHeightSum) / noHeightCount;
          }
    
          // last element takes all remaining space
          if (!relHeightElements.length) { absH = absHeightLeft; }
          else { absH = Math.round(freeHeight * relH / 100); }
    
          // anyway, height can't be negative
          if (absH < 0) { absH = 0; }
    
          c.rowFit.calcAbsHeight = absH;
          c.rowFit.calcRelHeight = relH;
    
          c.setHeight(absH);
          absHeightLeft -= absH;
        }
    
        for (var i=0, n = ct.items.length; i < n; i++) {
          var c = ct.items.itemAt(i);
          if(c.isSlider && c.el2resize) {
    //        this.checkRelHeight(c);
            var split = new Ext.SplitBar(c.el, c.el2resize.el, Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
            split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
            c.el2resize.sliderId = c.getId();
            c.el2resize = false;
          }
        }
    
        if(!this.rendered) { // keep watching for changes of items
          ct.on('add', this.ctAddItem, this);
          ct.on('remove', this.ctDelItem, this);
          this.rendered = true;
        }
      },
    
      // private - called from Ext.Container
      setContainer : function(ct){
        Ext.ux.layout.RowFitLayout.superclass.setContainer.call(this, ct);
        this._addSliders(ct);
      },
    
      // private
      _addSliders: function(ct) {
        var sh = ct.splitHeight || this.splitHeight;
        var skip1 = true;
        var n = ct.items.length;
        for(var i = n-1; i >= 0; i--) {
          var c = ct.items.itemAt(i);
    
          this.checkRelHeight(c);
          if(c.isResizable) { // !c.rowFit.hasAbsHeight) {
            if(skip1) {
              skip1 = false;
              continue;
            }
    
            if(c.split) {
              var slider = new Ext.Panel({height:sh, isSlider: true});
              slider.el2resize = c;
              slider.addClass('x-splitbar-y');
              ct.insert(i+1, slider);
            }
          }
        }
      },
    
      /**
       * Add event listener for container children
       * @private
       */
      itemListener: function(item) {
        item.ownerCt.doLayout();
      },
      _item_show: function(comp) {
        if(!comp.isSlider && comp.sliderId) {
          var sl = comp.ownerCt.findById(comp.sliderId);
          if(!sl.isVisible()) {
            sl.show();
            return;
          }
        }
        comp.ownerCt.doLayout();
      },
      _item_hide: function(comp) {
        if(!comp.isSlider && comp.sliderId) {
          var sl = comp.ownerCt.findById(comp.sliderId);
          if(sl.isVisible()) {
            sl.hide();
            return;
          }
        }
        comp.ownerCt.doLayout();
      },
      _item_expand: function(comp) {
        this._item_show(comp);
      },
      _item_collapse: function(comp) {
        this._item_hide(comp);
      },
    
      /**
       * Event listener for the container (on add, remove)
       * @private
       */
      ctAddItem: function(ct, comp, idx) {
        // TODO: ev. add slider & splitbar
        ct.doLayout();
      },
      ctDelItem: function(ct, comp) {
        // TODO: ev. remove slider & splitbar
        ct.doLayout();
      }
    
    });
    
    
    // Split adapter
    if (Ext.SplitBar.BasicLayoutAdapter) {
    
      /**
       * @param {Ext.SplitBar} splitbar to which adapter is applied.
       *   If supplied, will set correct minSize and maxSize.
       */
      Ext.ux.layout.RowFitLayout.SplitAdapter = function(splitbar) {
        if (splitbar && splitbar.el.dom.nextSibling) {
          var next = Ext.getCmp( splitbar.el.dom.nextSibling.id ),
              resized = Ext.getCmp(splitbar.resizingEl.id);
    
          // skip abs-height non-resizable components
          while(next && (next.collapsed || !next.isVisible() || !next.isResizable)) {
            next = Ext.getCmp(next.el.dom.nextSibling.id);
          }
    
          if (next) {
            //splitbar.maxSize = (resized.height || resized.rowFit.calcAbsHeight) +
            splitbar.maxSize = (resized.rowFit.hasAbsHeight ? resized.rowFit.calcAbsHeight : resized.getSize().height) +
                               next.getInnerHeight() - 1; // seems can't set height=0 in IE, "1" works fine
          }
          splitbar.minSize = resized.getFrameHeight() + 1;
        }
      }
    
      Ext.extend(Ext.ux.layout.RowFitLayout.SplitAdapter, Ext.SplitBar.BasicLayoutAdapter, {
    
        setElementSize: function(splitbar, newSize, onComplete) {
          var resized = Ext.getCmp(splitbar.resizingEl.id);
    
          // can't resize absent, collapsed or hidden panel
          if (!resized || resized.collapsed || !resized.isVisible()) return;
    
          // resizingEl has absolute height: just change it
          if (resized.rowFit.hasAbsHeight) {
            resized.setHeight(newSize);
          }
          // resizingEl has relative height: affects next sibling
          else {
            if (splitbar.el.dom.nextSibling) {
              var nextSibling = Ext.getCmp( splitbar.el.dom.nextSibling.id );
              // skip abs-height non-resizable components
              while(nextSibling && (nextSibling.collapsed || !nextSibling.isVisible() || !nextSibling.isResizable)) {
                nextSibling = Ext.getCmp(nextSibling.el.dom.nextSibling.id);
              }
    
              var deltaAbsHeight = newSize - resized.rowFit.calcAbsHeight, // pixels
                  nsRf = nextSibling.rowFit, // shortcut
                  rzRf = resized.rowFit,
                  // pixels in a percent
                  pctPxRatio = rzRf.calcRelHeight / rzRf.calcAbsHeight,
                  deltaRelHeight = pctPxRatio * deltaAbsHeight; // change in height in percent
    
              rzRf.relHeight = rzRf.calcRelHeight + deltaRelHeight;
    
              if (nsRf.hasAbsHeight) {
                var newHeight = nextSibling.height - deltaAbsHeight;
                nextSibling.height = newHeight;
                nextSibling.setHeight(newHeight);
              }
              else {
                nsRf.relHeight = nsRf.calcRelHeight - deltaRelHeight;
              }
            }
          }
          // recalculate heights
          resized.ownerCt.doLayout();
        } // of setElementSize
    
      }); // of SplitAdapter
    }
    
    Ext.Container.LAYOUTS['row-fit'] = Ext.ux.layout.RowFitLayout;
    still missing: better handling of add- and remove-events on the container to add/remove sliders and splitbars as well.

    Now if only someone extended the ColumnLayout to have resizable columns ;-)

    Comments?

  6. #16
    Ext User
    Join Date
    Nov 2007
    Posts
    110
    Vote Rating
    0
    ray007 is on a distinguished road

      0  

    Default


    I just found a little problem, probably also with the original version and not only with my modified one:
    internet explorer doesn't scroll the content of the items in the container if too large, while firefox and opera are doing just fine here. I'm getting a rendering error in a different place with those 2 browsers, but that's another story ...
    Does anybody have an idea what's going wrong here?

  7. #17
    Ext User
    Join Date
    Dec 2007
    Posts
    9
    Vote Rating
    0
    sgan is on a distinguished road

      0  

    Default Ext.ViewPort

    Ext.ViewPort


    Hi,


    I need to add a Ext.ViewPort to an existing jsp, basically render the viewport to a div which resides in the existing jsp page.

    I found the Ext.viewport(with all its panels within) always rendered starting at leftmost and topmost point of the browser(FireFox specifically).Is it correct to try to render a Ext.ViewPort into portion of JSP? For the viewport part seems to take over the whole screen.

    Thanks a lot,

  8. #18
    Ext User DigitalSkyline's Avatar
    Join Date
    Apr 2007
    Location
    Rochester, MI
    Posts
    461
    Vote Rating
    1
    DigitalSkyline is on a distinguished road

      0  

    Default


    You could've posted in help, but anyways to answer, no ViewPort is descendant of document.body, it can not reside in a div. For this you'll need to use a panel.

    ps - Isn't JSP irrelevant to the browser/discussion?

  9. #19
    Ext User
    Join Date
    Dec 2007
    Posts
    9
    Vote Rating
    0
    sgan is on a distinguished road

      0  

    Default Ext.ViewPort

    Ext.ViewPort


    Yep, you are right. I can not render the viewport to a div.

    What i tried is to put the viewport into a ext panel and then render the panel to a div.
    The div is within an existing JSP, my hope is to embed the previous panel to the page,
    what i saw is the panel (with viewport in it) occupy the full browser screen, which is not expected of my original attempt.

    Note:can the viewport not occupy the full screen or am i wrong in expecting it not?

  10. #20
    Ext JS Premium Member
    Join Date
    Sep 2007
    Posts
    4
    Vote Rating
    0
    mgeri is on a distinguished road

      0  

    Default


    Thanks for your work. Using GridPanel as items I could't get the horizontal scrollbar to show up. I changed the doLayout method to set also the panel width and now seems to work.

    Code:
    				onLayout : function(ct, target) {
    
    					Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this,
    							ct, target);
    
    					if (this.container.collapsed || !ct.items
    							|| !ct.items.length) {
    						return;
    					}
    
    					// first loop: determine how many elements with relative
    					// height are there,
    					// sums of absolute and relative heights etc.
    					var absHeightSum = 0, // sum of elements' absolute heights
    					relHeightSum = 0, // sum of all percent heights given in
    										// children configs
    					relHeightRatio = 1, // "scale" ratio used in case sum <>
    										// 100%
    					noHeightCount = 0, // number of elements with no height
    										// given
    					relHeightElements = []; // array of elements with 'relative'
    											// height for the second loop
    
    					var targetSize = target.getStyleSize();
    					
    					for (var i = 0, n = ct.items.length;i < n; i++) {
    						var c = ct.items.itemAt(i);
    
    						if (!c.isVisible()) {
    							continue;
    						}
    
    						// collapsed panel is treated as an element with
    						// absolute height
    						if (c.collapsed) {
    							var h = c.getFrameHeight();
    							absHeightSum += h;
    							c.setSize({width:targetSize.width, height: h});
    							
    						} else if (c.rowFit.hasAbsHeight) { // element that has
    															// an absolute
    															// height
    							absHeightSum += c.height;
    							c.setSize({width:targetSize.width, height: c.heigh});
    
    						} else { // 'relative-heighted'
    							if (!c.rowFit.relHeight) { // element with no
    														// height given
    								//noHeightCount++;
    								absHeightSum += c.getFrameHeight();
    								c.setSize({width:targetSize.width, height: c.heigh});
    							} else {
    								relHeightSum += c.rowFit.relHeight;
    								relHeightElements.push(c);
    							}
    							
    						}
    					}
    
    					// if sum of relative heights <> 100% (e.g. error in config
    					// or consequence
    					// of collapsing/removing panels), scale 'em so it becomes
    					// 100%
    					if (noHeightCount == 0 && relHeightSum != 100) {
    						relHeightRatio = 100 / relHeightSum;
    					}
    					
    					var freeHeight = target.getStyleSize().height
    							- absHeightSum, // "unallocated" height we have
    					absHeightLeft = freeHeight; // track how much free space we
    												// have
    
    					while (relHeightElements.length) {
    						var c = relHeightElements.shift(), // element we're
    															// working with
    						relH = c.rowFit.relHeight * relHeightRatio, // height of
    																	// this
    																	// element
    																	// in
    																	// percent
    						absH = 0; // height in pixels
    
    						// no height in config
    						if (!relH) {
    							relH = (100 - relHeightSum) / noHeightCount;
    						}
    
    						// last element takes all remaining space
    						if (!relHeightElements.length) {
    							absH = absHeightLeft;
    						} else {
    							absH = Math.round(freeHeight * relH / 100);
    						}
    
    						// anyway, height can't be negative
    						if (absH < 0) {
    							absH = 0;
    						}
    
    						c.rowFit.calcAbsHeight = absH;
    						c.rowFit.calcRelHeight = relH;
    						c.setSize({width:targetSize.width, height: absH});
    						
    						absHeightLeft -= absH;
    					}
    
    					for (var i = 0, n = ct.items.length;i < n; i++) {
    						var c = ct.items.itemAt(i);
    						if (c.isSlider && c.el2resize) {
    							// this.checkRelHeight(c);
    							var split = new Ext.SplitBar(c.el, c.el2resize.el,
    									Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
    							split
    									.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
    							c.el2resize.sliderId = c.getId();
    							c.el2resize = false;
    						}
    					}
    
    					if (!this.rendered) { // keep watching for changes of
    											// items
    						ct.on('add', this.ctAddItem, this);
    						ct.on('remove', this.ctDelItem, this);
    						this.rendered = true;
    					}
    				}