height on some components is 0 after using setContainer to change a layout

I'm developing a web app that has two different layouts, one for small screens and one for large screens.
The way I'm switching between those layouts is by using setContainer() to choose where all components will be displayed.
However, when I switch the layout from large screen, to small screen and then back again, the heights on some of the components become 0. I have tried render() and resized() after the container switch, but nothing seems to make the components render correctly except a page refresh, which I cannot do because then I loose the unsaved data.

Here is a fiddle demonstrating the issue:
http://jsfiddle.net/plague/CGm79/

To reproduce, just run the example in fullscreen, resize the window until it switches layout and then go fullscreen again.
As you can see, the Comments list will initially show it's content, but after you've switched layout to mobile and then back again, the content in the list is not shown.

If you click on the button when in mobile layout and then go to the full layout again, the content will show, but not otherwise.

How do I force it to correctly recalculate it's height after I switch layout?

Comments

  • I added a couple of enyo-fit classes in scroller div's. http://jsfiddle.net/CGm79/13/
  • edited November 2013
    Thanks for the tip.
    Unfortunately I cannot do that, as there are several more components above that comments list and if I put enyo-fit as you suggested, the comments list will be at the top of the page.

    Edit: to clarify, enyo-fit adds position: absolute to the component and I cannot do that.
  • I updated your fiddle at http://jsfiddle.net/CGm79/21/.

    You're trying to render during reflow which is called during rendered(). That doesn't work very well. I put your change code and stuck it into a enyo.job and now the resizing works for me.
  • Yea I thought that was what was happening, however your example doesn't work for me, there's no difference in behaviour even if I set the timing to 1000 on the job. :/
    Tested in Chrome, Firefox and Opera.
  • edited November 2013
    Hmmm, I was testing on Chrome on Mac... are you looking at http://jsfiddle.net/CGm79/21/embedded/result/? What I see is that it starts out showing all the controls, then I resize it down and just see the comment button, then I size it back up and I see everything appear like it had.

    Update: if I use http://fiddle.jshell.net/CGm79/21/show/light/ I don't see the content reappearing... something about how the result page was wrapping the container was causing it to act differently. I'll have to investigate more.
  • Thanks for taking time to help.

    I've now tested your latest links on another computer and neither of those examples work for me in any browser on Windows.
    Tested this time with Chrome, Opera 12, latest Opera Developer build (Chromium based) and Internet Explorer 10.

    Weird that it seems to work sometimes on Mac..
  • The iframe version stopped working for me too... not sure why it worked once. Anyway, I'd suggest debugging through the reflow code for fittable and see what's going wrong. I won't have time to check that until much later today.
  • No worries, take your time. I very much appreciate all the help I can get.

    I won't be able to debug the reflow code until tomorrow at work anyways (it's 8 pm here), as I don't have the tools or sourcecode on my home computer.
  • I have not had any luck so far in debugging the reflow code.
    It does run but I haven't been able to figure out why it doesn't do the correct size calculations.
  • edited November 2013
    I'm still stuck, I just can't figure out how to solve this.
    "You're trying to render during reflow which is called during rendered(). That doesn't work very well."
    That definitely causes problems. However, I must render after switching container, in order for the content to show up on the screen, and I must switch container when the window switches to and from narrow screen size.

    Is there a way to detect an isScreenNarrow event or something? As in, detecting when the screen turns narrow?

    This is why I have my code in reflow, as I can't find any other way of detecting when the screen changes size...

    If I can just listen to some event, then I could move that code out from reflow and possibly avoid this problem?
  • You could use an enyo.Signals to listen for onresize and do your isScreenNarrow check there.
  • edited November 2013
    Thanks for the tip, didn't help though, it behaves just like before. :(
    My guess is it's still trying to render during reflow. I have no idea how to avoid that??
  • So I've been away on vacation for a week, but I'm back and have continued trying to solve this issue without any luck. :(

    I've debugged the reflow code for the fittable, but I can't see why it get's the wrong size. The fittable never shows the correct size, it always shows 55px for the height (= the height of the titlebar) every time it runs, so it never receives the parent height apparently.

    My guess is that it simply runs too early, before the parent has calculated it's height??

    But as I don't have deep knowledge of the inner workings of Enyo, this is where I get stuck.

    I have no idea whatsoever how to move forward.
    I need to change the layout when the window width changes below/above a certain size and after I've changed layout it has to render or the new layout will not be displayed on the screen.

    How can I do that if I can't do it during reflow?
  • I tried going another route and using an enyo.Repeater instead of an enyo.List for the comments. The repeater had to be wrapped with an enyo.Scroller, which needed a max-height set on it (setting fit:true caused some other side effects) - let me know if this is a viable solution: http://jsfiddle.net/aarontam/CGm79/36/embedded/result/
  • edited December 2013
    There are a few problems with that.
    1. I don't neccesarily want to have to provide a max-height, as I would like it to be autosized to fit the remaining space on the screen. However, if that turns out not to be possible then I can live with it.
    2. This is not the only component in my project to be affected by the reflow issue. I have some components that on some devices (Safari on Mac and iOS mainly) don't get the right coordinates when I switch layout, they "jump down" a bit on the page.
    I also have issues with some components not being clickable after a layout switch, even though they seem clickable as they still have their click animation, nothing happens when clicking on them so it seems they can't get any focus or something.

    So even if the comments list can be fixed so it doesn't have height: 0 after a layout switch, there are still other components affected by the problem that can't be fixed the same way.


    Edit:
    Actually, it seems Apple has made some update to Safari very recently so the issue of the components not getting the right coordinates after a layout switch seem to have been fixed by them (or it's just a coincidence). They still render some components wrong on first page load though, but funnily enough not after a layout switch so I might be able to fix that with some hack.

    So I'll try your approach and see if it may be enough for the time being.
    Thanks. :)
    I'll post again if I find any issues.
  • Unfortunately the Repeater seems to be waaaaay too slow. It takes forever to fill it and whenever I want to change it's content, it takes a very long time. The more content it has, the longer it takes to fill it.
    Whenever it's filling the content, nothing shows on screen and it becomes completely unresponsive (can't scroll it, can't click on any button belonging to it).

    So unfortunately it seems I have to use a List for the comments. :/
  • If I wrap the List in a div with display: block; and set that div to fit: true instead of the List and then force the List to have a fixed height, then it kinda sorta works. However, that div wrapper still get's a height: 0 after I switch layouts so even though the List will be visible and work, as it has a fixed height, it's not a correct solution.

    Here's a fiddle showing what I mean:
    http://jsfiddle.net/plague/7hc9x/1/

    If anyone has a better solution, I'd very much appreciate it.
  • edited December 2013
    Ah yes List is more performant for large numbers of items than Repeater, since it uses the flyweight pattern.

    I'm not sure you even need to wrap the List in another div; you could set the FittableColumns .layoutfull-panel-container-bottom to have a fixed height (instead of max-height) and it seems to work: http://jsfiddle.net/aarontam/7hc9x/2/

    One thing I noticed is that if you change the viewport so that the mobile view appears, and you tap the "Comments" button to display the comments panel (and close it), and then expand the viewport so that the fullscreen view appears again, the comments appear properly. I'll dig into this some more to see what other options there are.
  • edited December 2013
    Going off the panels observation, I made a small tweak to your original code to directly set the indices of the panelBodys Panels component (the indices can be made dynamic as necessary) when changing layouts: http://jsfiddle.net/aarontam/CGm79/37/

    Obviously this isn't super elegant or the cleanest, but maybe that will work as a solution for now without updating the core. It seems that the height:0 set on the list is caused by the list being inside an inactive panel in the mobile layout initially, and even after the list's container is changed to the full layout, the reflow layout calculations never update the height:0 of the list (I think you observed this when you stepped through the reflow code for the fittable and it only accounted for the titlebar height). There is something odd with how the reflow code is handling height:0 on the list - I removed this attribute on the fly after I went from full to mobile back to full, then proceeded to call resized() on the view and it properly displayed and sized the list. Will dig around some more to figure out the exact cause.

    EDIT:
    Came across this old bug (https://enyojs.atlassian.net/browse/ENYO-569) and alternatively, removed one of the nested Panels: http://jsfiddle.net/aarontam/CGm79/38/.
  • Thanks for your help in tracking down what is happening. I really appreciate it.

    Your latest workarounds won't work in my project unfortunately, as I need to keep the "panelTestcrap" panel (I have other panels in it's place, so I put that there just for this example to demonstrate the behaviour).
    I also can't directly set the indices when switching to the mobile layout, as I have lots of panels there and comments is the last panel to be opened by default.

    However, I think I can use your suggestion of setting a fixed height on .layoutfull-panel-container-bottom until the original bug goes away.

    If I understand correctly, ENYO-569 and ENYO-548 (https://enyojs.atlassian.net/browse/ENYO-548) are solved by the same fix, but that fix has yet to be released?
    In ENYO-548 it says "Fix Version/s: Post-2.3", so I'm guessing the fix has been postponed to after 2.3 stable due to the risk of it breaking something else?
    Is the fix downloadable somewhere so that I may test it in my codebase? (Can't find anyehere to download on atlassian)
    I have to make a release of my project before january, so I don't really have the luxury of waiting for post-2.3 fixes unfortunately.
  • That fix version was set long, long ago. I don't think we've revisited that bug since mid-2012.
  • edited December 2013
    @plague: An alternative to setting a fixed height on .layoutfull-panel-container-bottom is to programmatically set height:100% on the list itself after the call to render when changing back to the full layout (the list will be contained by the max-height of its container): http://jsfiddle.net/aarontam/CGm79/39/

    I tried reverting the changes from the commit that addressed ENYO-569 and ENYO-548 (https://github.com/enyojs/enyo/pull/110) and it actually didn't make a difference in this particular case, even though someone had a similar issue (https://enyojs.atlassian.net/browse/ENYO-569?focusedCommentId=11165&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-11165), though your particular case involves nested panels in addition to changing parent containers.

    So what appears to be happening is that the comment list shows up in a hidden panel in the mobile layout, so it has a natural height of 0. When the parent container is changed back to the full layout and a render is called, the natural height is still 0, and the reflow code uses an element's container to calculate what the new height should be. The container is a fittable and its height is the sum of its children's heights = toolbar height + list height (which is 0), leaving only room for the toolbar and a calculated height of 0 for the list (kind of a circular dependency). When we activate the panel that contains the list, the panel is made visible and the list has a non-zero natural height (equal to the height of the window) that doesn't change back to zero when the panel is closed (as we're using some CSS transforms instead of re-hiding), which is why the proper behavior occurs in that case. And when we don't have nested panels, the panel for the comment list is not hidden in the mobile layout as it is at the first level of panels, so again the list has the same non-zero natural height.

    In any case, the fix may not be a simple one (we're going to have to reexamine how we handle nested panels and visibility) and if the alternative solution I just proposed is workable for you (avoids having to set a hard-coded height), I would probably roll with that for now.
  • I've tried your latest suggestion, and it works aswell.
    Based on all the info provided here, I've decided to rethink a bit and settled for a fixed height for now.
    I've managed to (hopefully) get my code working on all major browsers (that was a pain).
    Ofcourse it involves some more or less ugly hacks in some places but it works. ;)

    Naturally, I would like to get rid of most of the hacks, but for now it works well enough for me to be able to make a release.

    Thanks a ton for all your help!
Sign In or Register to comment.