PDA

View Full Version : Layout Question



mschwartz
27 Dec 2010, 8:14 AM
I spent several hours over the weekend trying to get a specific layout to work, but couldn't.

I have a viewport with north/south/east/west/center. The center is a card layout. In the card layout, I wanted to implement something (exactly) like viewing a thread on this message board.

So I figure I want a panel to put in the center/card layout. The bbar is a paging toolbar. The store is 1 to 20 posts/comments.

Look at any thread on this site. It seems like each post would be a panel (see attachment). The title would be the blue bar with the post date/time. The panel itself would be border layout (others might work), with west region being the user bit (avatar, user name, user group title, # posts, etc.) and the center region being the post content. The bbar would be the "add reputation," "report post", "reply," "reply with quote" buttons.

In my store's onload handler, I implemented code that removed all items from the "thread" panel and then added a series of new panels to it, one per post. (It was horribly slow, ExtJS 3.2.1 BTW).

The issues I faced were the post panels wouldn't render with any height. All that was visible were the title and bbar. The default/component layout docs say that the child items are NOT resized, which makes sense. Some permutations of config options I tried giving a fixed height: did work. I tried form layout, vbox layout, anchor layout, and just about every other layout that made sense, and none of those autoHeight sized the post panels.

Other issues I had were getting scrollbars on the panel - if there were enough posts that the center region of the card layout needed to vertical scroll. In almost every permutation of config options I tried, and nesting panels and so on, I could only get a vertical scrollbar with a horizontal scrollbar as well that scrolled right about 20 pixels. Or posts initially rendered and visible (e.g. don't need to scroll to make them visible) would be too wide (the scrollbar obscured the right side of the posts) but the ones I scrolled down to see were rendered proper width.

I ended up with a working solution that was based upon pure HTML. I used <div class="x-panel-title" (or whatever the class is) to make the title bar look proper. I used a table to simulate the post content/user bit. I added a div with an id determined by the post # and added Ext.Toolbar with renderTo or applyTo to those divs to get the bbar effect. I keep track of the toolbars in an array so I can call destroy() on them when the panel is destroyed or the store reloaded.

Am I missing something?
23983

Condor
27 Dec 2010, 10:10 AM
The panel inside the card layout should be layout:'anchor' and the individual post panels should be anchor:'-'+Ext.getScrollBarWidth().

ps. Also have a look at my ComponentDataView user extension.

mschwartz
27 Dec 2010, 11:47 AM
One more thing...

If you do:
var n = node.removeChild(someNode, false);
node.insertBefore(n, node.firstChild);

I'm not seeing the node displayed anymore.

Condor
27 Dec 2010, 12:02 PM
A tree knows how to move nodes; you don't need to remove a node first.

mschwartz
27 Dec 2010, 12:06 PM
Ah, but I do.

The tree in question is something like a history display. I want the most recently selected node moved to the top.

Condor
28 Dec 2010, 12:04 AM
I mean, you just insert a node that is already in the tree somewhere else. The tree will automatically move the node in that case.

So you only need:

node.insertBefore(someNode, node.firstChild);

mschwartz
28 Dec 2010, 6:13 AM
Thanks Condor, I'll try it.

This raises a good question, I think. What's the point in having the remove() function's 2nd parameter?

Condor
28 Dec 2010, 6:25 AM
Good question. I don't see it used anywhere...

mschwartz
28 Dec 2010, 6:33 AM
One more point to raise, and it may be a bug. Feel free to split this post off into a thread and move it accordingly.

With a panel and preventBodyReset to true, the following code does not work as expected in chrome:


<table border="0" cellspacing="0" cellpadding="0">
<tr><td style="border: 1px solid">...</td><td style="border: 1px solid">...</td>...</tr>
</table>


You don't get cellspacing of 0, it's actually 2 because of a browser specific attribute that isn't being reset. -webkit-border-horizontal-spacing and -webkit-border-vertical-spacing should be 0 but are 2.

A plain HTML page with the above HTML renders properly in Chrome. Those webkit attributes are 0 by default. I mean, in the panel, you see two bordered cells with a gap of 4 px between them, but in the plain HTML page, there is no gap.

Cheers

Condor
28 Dec 2010, 6:51 AM
Yes, that's a bug.

ps. Could you repost it? I haven't figured out yet how to split off a single post from a thread into a new thread.

mschwartz
28 Dec 2010, 7:13 AM
Done

http://www.sencha.com/forum/showthread.php?119726-preventBodyReset-issue

mschwartz
28 Dec 2010, 7:20 AM
OK, another layout question.

In the viewport's center region, the card layout, if I show a card that has a scrollbar (taller than the browser), and scroll to the bottom, then switch cards and switch back to the card with the scroller, the scroller isn't in the same position. Like it's scrolled to the top, or up some number of pixels.

Condor
28 Dec 2010, 7:27 AM
Haven't seen that before. Maybe the browser does that when an element is hidden with display:none.

Try if adding hideMode:'offsets' to the card items helps.

mschwartz
14 Jan 2011, 6:41 AM
So I tried everything but the ComponentDataView extension that was suggested in this thread, and the results are the same.

I see titlebar and bbar with the body part of the panel's height set to 0. Examining the HTML with Chrom dev tools, I see the content is in the body proper and it all has the right computed height, but one of the wrapping div elements generated by Ext around all that has its height set to 0.

Condor
14 Jan 2011, 7:43 AM
Must be a layout configuration problem. Can you post your layout?

mschwartz
14 Jan 2011, 7:57 AM
Must be a layout configuration problem. Can you post your layout?

The code is here:

http://code.google.com/p/helma-community/source/browse/trunk/helma-community/apps/Community/client/Plugins/Forums/ThreadView.js

The relevant code is in renderComment()

Right now it renders HTML that looks like a Panel.

At line 41, I changed layout from 'fit' to 'anchor'

renderThread() function would do a me.add() with a panel configured with title, layout 'border', west region html content returned by Renderers.userBit(), center region html content returned by Renderers.renderComent()

anchor set as you suggested in one of the earlier posts in this thread.

The width of the panels was correct, leaving room for a scrollbar.

The panels only show the title bar and the bbar - the borderlayout in between has height of 0 when examining it with Chrome dev tools.

No doLayout() call on any CMP, be it the viewport or the card itself changed anything.

mschwartz
14 Jan 2011, 8:19 AM
Some screenshots:


What the app looks like:
http://sportstwo.com/img/figure_1.PNG

What looking at a forum looks like:
http://sportstwo.com/img/figure_6.PNG

Top of viewing a thread:
http://sportstwo.com/img/figure_7.PNG

Thread scrolled so you can see bottom of one post and top of the next one (the issue is here):
http://sportstwo.com/img/figure_8.PNG

mschwartz
17 Jan 2011, 6:29 AM
Turns out that what I'm doing is problematic. Over a slow network connection, a person can hit the refresh button fast enough to cause multiple store.load() to be ongoing at once. The code that renders the HTML and toolbars for the thread view renders two toolbars on the posts.

I'm not sure why it's doing it, since JavaScript is supposed to be single threaded.

I'll figure it out and fix it, no doubt.

The issue/question still remains. How to use actual Ext.Panel instead of having to render the HTML myself and track the toolbars.

Condor
17 Jan 2011, 6:38 AM
So you want a store-bound component (e.g. DataView) that contains components (e.g. Panels).

ComponentDataView wasn't really created with this in mind, but you could modify it to do this.

mschwartz
17 Jan 2011, 6:40 AM
So you want a store-bound component (e.g. DataView) that contains components (e.g. Panels).

ComponentDataView wasn't really created with this in mind, but you could modify it to do this.

Well, what I'm doing mostly works, but it's not ideal.

The question is why is ExtJS setting one of the panel wrap el's (of each post panel) to height 0?

I set the panels to autoHeight: true... Examining the DOM shows the body's div with my HTML in it has a height of 300+ px.

mschwartz
17 Jan 2011, 6:42 AM
Another approach might be to render...



<div id="post1"></div>
<div id="post2"></div>


... up to "page size" post#'s and then use renderTo or applyTo for each Panel.

Condor
17 Jan 2011, 6:47 AM
That's what ComponentDataView would do, but you still wouldn't get the benefit of automatically sizing the panels by the parent container layout.

Can't you create the panels in the store load event and add them to the container? The only problem with that is that the panels won't respond to store changes (add, update, delete, datachange etc).

mschwartz
17 Jan 2011, 6:56 AM
The HTML (or panels) are created in the store's load event handler.

http://code.google.com/p/helma-community/source/browse/trunk/helma-community/apps/Community/client/Plugins/Forums/ThreadView.js

Look at the code... store's load listener calls me.renderThread() which currently renders via HTML, though I've hacked in/out the code to render panels with code like:



function renderComment(comment, commentNum) {
me.add({
layout: 'border',
autoHeight: true,
title: 'Post #' + commentNum,
anchor: '-'+Ext.getScrollBarWidth(),
items: [
{
region: 'west',
width: 200,
html: Renderers.userBit(comment)
},
{
region: 'center',
html: Renderers.comment(comment)
}
],
bbar: new Ext.Toolbar({
...
})
});
}


(Using anchor layout for the card)

The point of using a store is so the paging toolbar works for pagination. Basically to perform this functionality of vB4/this site:

24322

Condor
17 Jan 2011, 7:04 AM
I got lost somewhere... What whas the actual problem you had?

ps. A border layout can't be autoHeight:true. Try using layout:'column' instead.

mschwartz
17 Jan 2011, 7:10 AM
LOL

The problem is I have a card layout in the center region of my viewport. When you view a thread, I want to render the thread posts linearly down the page, like you see on this current page.

A single vB4 post in a thread looks a lot like a Panel to me. Your last post has a title of "Today 7:04 AM" (for my timezone). The body looks like column or table or border layout. The west region is your avatar, your name, Ext-Community Support Team, # posts, etc. The center region is your post, signature, etc. The bottom is a bbar with "Reply", "Reply with Quote", etc., buttons.

The bottom of the page looks like a paging toolbar as I posted a screen shot in post #23. Add a "Reply to Thread" button to that.

My issue is that doing card.add({}) is rendering panels that have just the title bar, 0 height for the column/table/border layout region, and then the bbar. So it's just title/bbar, title/bbar, title/bbar going down the page. The userBit (avatar, user name, #posts, etc.) and post body have 0 height so they're not shown.

Again, examining the DOM with chrome tools shows the userBit and post body do have height of 300+ px (or whatever the length of the post is), but one of the wrap el's generated by ExtJS around the panel has its height set to 0.

Condor
17 Jan 2011, 7:18 AM
You can't use border layout as I already said, but column and table should both work.

The problem is probably that autoHeight:true is evaluated when the card is still hidden and the panel has height:0 (because of the default hideMode:'display'). Did you already try creating the card with hideMode:'offsets'?

mschwartz
17 Jan 2011, 7:23 AM
The card is already shown when the panels are added.

I'll try the column layout when I get home from work.

I tried stepping through a call to doLayout(), but my first attempt at doing this was after the panels are rendered. I tried calling doLayout() with force=true as well.

Something in there is setting the panel's body wrap el to height 0.

I'd love it if the borderlayout is the problem.