1. #1
    Sencha User
    Join Date
    Mar 2010
    Posts
    11
    Vote Rating
    0
    Josh LOL is on a distinguished road

      0  

    Default [Ext 4.1 beta 3] Strange layout on grids rendered into elements with display:none

    [Ext 4.1 beta 3] Strange layout on grids rendered into elements with display:none


    This has been tested against Ext 4.1 beta 3.

    I'm having problems with Ext.grid.Panel widgets that are rendered into a <div> whose display is set to 'none'. What happens is that when the parent div is finally made visible the grid appears as if it has only been through a partial layout.

    I've created a simple example that demonstrates this behavior, the following screenshots are of 2 identical grids, one initially rendered into a normal div, the other into a div with style="display:none;". To display the differences there is a single button that toggles the visibility of the parent div's on click.

    This is what the example first looks like on page load:


    ss-initiallyrendered.jpg

    This is how things look after the visibility is toggled, the expectation is that the second grid should look the same as the first screenshot grid. As you can see the title and bottom toolbar are missing.

    ss-initiallynotrendered.jpg
    Here is the page source used to generate this example:

    HTML Code:
    <html>
        <head>
            <!-- ExtJS 4 beta 3 includes -->
            <link rel="stylesheet" type="text/css" href="js/ext-4.1.0-beta-3/resources/css/ext-all.css">
            <script type="text/javascript" src="js/ext-4.1.0-beta-3/ext-all-debug.js"></script>
            
            <!-- This is pointing to the javascript snippet further down the post-->
            <script type="text/javascript" src="js/Main.js">
        </head>
    
        <body>
            <div id="div1" style="position: absolute; left: 16px; top: 30px; width: 300px; height: 300px; z-index: 10;">
            </div>
    
            <div id="div2" style="position: absolute; left: 316px; top: 30px; width: 300px; height: 300px; z-index: 10; display: none;"></div>
        </body>
    
    </html>

    Here is the javascript:

    Code:
    var flipDisplay = function(el) {
        var display = el.getStyle('display');
        if (display && display === 'none') {
            el.setStyle('display', 'inline');
        } else {
            el.setStyle('display', 'none');
        }
    };
    
    var createPanel = function(title, renderTo) {
        return Ext.create('Ext.grid.Panel', {
            title : title,
            renderTo : renderTo,
            hideHeaders : true,
            columns : [ {
                dataIndex : 'field1',
                flex : 1
            } ],
            store : Ext.create('Ext.data.Store', {
                fields : [ {
                    name : 'field1'
                } ],
                data : [ {
                    field1 : 'val1'
                }, {
                    field1 : 'val2'
                } ]
            }),
            width : 300,
            height : 300,
            bbar : [ {
                xtype : 'button',
                text : 'myButton'
            } ]
        });
    };
    
    Ext.onReady(function() {
        //The first panel (initially visible)
        var p1 = createPanel('I am panel #1', 'div1');
        var p2 = createPanel('I am panel #2', 'div2');
    
        Ext.create('Ext.button.Button', {
            text : 'Flip Visibility',
            renderTo : Ext.getBody(),
            handler : function() {
                flipDisplay(Ext.get('div1'));
                flipDisplay(Ext.get('div2'));
            }
        });
    });

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

      0  

    Default


    Display inline is not valid for elements which contain block level elements. Use "" to restore a div to its default display value which is "block"

  3. #3
    Sencha User
    Join Date
    Mar 2010
    Posts
    11
    Vote Rating
    0
    Josh LOL is on a distinguished road

      0  

    Default


    Thanks for the response, unfortunately I tried replacing the 'inline' with an empty string '' and there is no difference under FF 10.0.2 or Chrome 17.0.963.78 m.

  4. #4
    Sencha User
    Join Date
    Mar 2010
    Posts
    11
    Vote Rating
    0
    Josh LOL is on a distinguished road

      0  

    Default


    Because I have no control over the divs the panels are being rendered into, they are being managed by another framework, I've been forced into coming up with an ugly workaround.

    This workaround is completely predicated on being able to figure out where in the DOM the display attribute will be altered. In my case I am lucky because the node in question can be easily identified by using its class.

    This is by no means an ideal fix, it's forcing unnecessary layouts and could stand for some basic optimisation. The reason I didn't go down this path myself is because I'm hoping this gets fixed in an upcoming release.

    HTML:
    Code:
    <html>
        <head>
            <!-- ExtJS 4 beta 3 includes -->
            <link rel="stylesheet" type="text/css" href="js/ext-4.1.0-beta-3/resources/css/ext-all.css">
            <script type="text/javascript" src="js/ext-4.1.0-beta-3/ext-all-debug.js"></script>
            
            <!-- This is pointing to the javascript snippet further down the post-->
            <script type="text/javascript" src="js/Main.js">
        </head>
    
        <body>
            <div id="div1" style="position: absolute; left: 16px; top: 30px; width: 300px; height: 300px; z-index: 10;">
            </div>
    
            <div id="div2" style="position: absolute; left: 316px; top: 30px; width: 300px; height: 300px; z-index: 10; display: none;"></div>
        </body>
    </html>
    Javascript:
    Code:
    var flipDisplay = function(el) {
        var display = el.getStyle('display');
        if (display && display === 'none') {
            el.setStyle('display', '');
        } else {
            el.setStyle('display', 'none');
        }
    };
    
    var createPanel = function(title, renderTo) {
        return Ext.create('Ext.grid.Panel', {
            title : title,
            renderTo : renderTo,
            hideHeaders : true,
            columns : [ {
                dataIndex : 'field1',
                flex : 1
            } ],
            store : Ext.create('Ext.data.Store', {
                fields : [ {
                    name : 'field1'
                } ],
                data : [ {
                    field1 : 'val1'
                }, {
                    field1 : 'val2'
                } ]
            }),
            width : 300,
            height : 300,
            bbar : [{
                xtype : 'button',
                text : 'myButton'
            }],
            listeners : {
                //This is the workaround in question. 
                //The strategy is to find the parent div whose 'display' attribute will be changing,
                //from that we listen for DOMAttModified events and force layouts whenever any attributes change
                afterrender : function(container) {
                    console.warn('Implementing a workaround for Ext 4.1.0 - beta 3');
    
                    //Find the parent DOM element containing this panel
                    var el = container.getEl();
                    var parentDiv = el.findParentNode('div.mySpecialDiv', 10, true); //This is for my example, your lookup will vary
    
                    var id = parentDiv.id;
                    parentDiv.on('DOMAttrModified', function(e, t, eOpts) {
                        //we are only interested in change events for the parentDiv
                        if (t.id !== id) {
                            return;
                        }
    
                        //This won't be conducive to 'good' performance but it's our only option.
                        container.doLayout();
                    });
                }
            }
        });
    };
    
    Ext.onReady(function() {
        //The first panel (initially visible)
        var p1 = createPanel('I am panel #1', 'div1');
        var p2 = createPanel('I am panel #2', 'div2');
    
        Ext.create('Ext.button.Button', {
            text : 'Flip Visibility',
            renderTo : Ext.getBody(),
            handler : function() {
                flipDisplay(Ext.get('div1'));
                flipDisplay(Ext.get('div2'));
            }
        });
    });

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

      0  

    Default


    Not sure what we can do.

    We cannot detect when some DIV is shown (apart from doing what your code does, and we don't know what to look for being shown)

    It's not being layed out because it's hidden.

    So it does need a first layout when shown.

    What you should do is only call the layout

    Code:
    if (!container.componentLayoutCounter)
    Or better still, only render it on show of the div.

    Deferred rendering - that's what we do in TabPanels.

  6. #6
    Sencha User
    Join Date
    Mar 2010
    Posts
    11
    Vote Rating
    0
    Josh LOL is on a distinguished road

      0  

    Default


    So because this was working for us in Ext 3, am I right in assuming that Ext 3 was performing 'unnecessary' layouts which has since been fixed in Ext 4?

    I'd love to be able to do some proper deferred rendering but our real world use case is dependent on an old version of the Google maps API which doesn't expose any kind of change event, hence my horrible workaround. I'm assuming the deferred rendering in tab panels is triggered whenever the tab change occurs (something we can't listen for in our case).

    Thanks again for your help with this Animal, chances are that I'll keep this workaround (tweaked slightly for performance) for now and longer term look at embedding and styling our own custom tab panels in place of the GMap tabs.

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

      0  

    Default


    It's very probably that 3 was doing that extra layout for you, and in 4 we try to rigorously use as few layouts is possible.

    Yes, deferred rendering in any card layout is triggered by that card being shown. There's no DOM there at all for the card until it's required to be viewed.

Thread Participants: 1

Tags for this Thread

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..."