DeckLayoutPanel in a HTMLPanel with HTML table doesn't display - gwt

I have a GWT app with one main panel showing a table of PostgreSQL instances. I want the app to show other kinds of instances, e.g. Redis instances. So I'm initially wrapping the main panel in a DeckLayoutPanel to swap out the PostgreSQL panel with a Redis panel. There will a vertical menu on the left side that the user will use to select the type of instance to show.
Adding DeckLayoutPanel to the UI XML causes the main panel to not display, although I do see the content in a DOM inspector.
Here's the original, working UI, without g:DeckLayoutPanel:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:HTMLPanel>
<table width="100%" border="1">
<tr>
<td colspan="2" align="left">
Logo
</td>
<td colspan="2" align="right">
Hello John
</td>
</tr>
<tr>
<td colspan="4">
<g:VerticalPanel ui:field="instancesPanel">
<g:Label ui:field="mainErrorLabel" />
<g:FlexTable ui:field="flexTable" />
<g:HorizontalPanel>
<g:TextBox ui:field="createInstanceTextBox" />
<g:ListBox ui:field="createInstanceVersionsListBox" />
<g:Button ui:field="createInstanceButton">Create</g:Button>
<g:Label ui:field="createInstanceErrorLabel" />
</g:HorizontalPanel>
</g:VerticalPanel>
</td>
</tr>
<tr>
<td>Help</td>
<td>About</td>
<td>Contact</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>
If I remove the g:HTMLPanel and also the HTML table, trimming it to, this works:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:DeckLayoutPanel ui:field="deckLayoutPanel">
<g:VerticalPanel ui:field="instancesPanel">
<g:Label ui:field="mainErrorLabel" />
<g:FlexTable ui:field="flexTable" />
<g:HorizontalPanel>
<g:TextBox ui:field="createInstanceTextBox" />
<g:ListBox ui:field="createInstanceVersionsListBox" />
<g:Button ui:field="createInstanceButton">Create</g:Button>
<g:Label ui:field="createInstanceErrorLabel" />
</g:HorizontalPanel>
</g:VerticalPanel>
</g:DeckLayoutPanel>
</ui:UiBinder>
I'm using an HTML table here since I'm not a front-end designer and I have similar HTML for the non-GWT JSP pages (using a JSTL tag) so want to make sure the GWT and non-GWT pages render the same.
Should I be using something else than a table? Should I switch to divs for placement instead? Is using a g:DeckLayoutPanel in an HTML table not supported? How is one supposed to get identical HTML pages for GWT and non-GWT pages if one needs to use only GWT layout widgets?
BTW, I tried using RootPanel and that didn't work either with the HTML page.
I'm binding to it using:
interface Binder extends UiBinder<HTMLPanel, MyWebApp> { }
private static final Binder binder = GWT.create(Binder.class);
#UiField
DeckLayoutPanel deckLayoutPanel;
#UiField
VerticalPanel instancesPanel;
#Override
public void onModuleLoad() {
HTMLPanel outer = binder.createAndBindUi(this);
// Tweak a bunch of settings on the UI elements.
...
RootLayoutPanel.get().add(outer);
deckLayoutPanel.showWidget(instancesPanel);
}
The HTML hosting the page is this:
<!doctype html>
<%# page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
<link type="text/css" rel="stylesheet" href="MyWebApp.css">
<title>MyWebApp</title>
<script type="text/javascript" language="javascript" src="MyWebApp/MyWebApp.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
</body>
</html>

DeckLayoutPanel in a HTMLPanel
The problem is part of the title...
The short answer is: Do not nest **LayoutPanels in anything other than a **LayoutPanel unless you set a fixed size for it.
**LayoutPanels are meant for applications that that have a static layout that is defined from the outer to the inner. If you only user **LayoutPanels for the outer layout, it works. In your second code example you noticed exactly this behavior.
A html table works different, it needs it's content to define a size and grow with it. As **LayoutPanels do not grow with their contents, they have a size of 0x0px.
I answered a similar question lately (link). Possibly it answers different aspects of this problem.

Related

GWT: How to embed a SimplePager into a DataGrid

Currently, DataGrid doesn't include a SimplePager. One must create a composite and wrap a grid and a pager into a FlowPanel. Is there a way you can create a wrapper CDataGrid (that extends DataGrid) that includes SimplePager?
I think that you can use UiBinder to make this possible, you can check at the showcase sample here that shows this:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c="urn:import:com.google.gwt.user.cellview.client">
<g:DockLayoutPanel
unit="EM">
<!-- DataGrid. -->
<g:center>
<c:DataGrid
ui:field='dataGrid' />
</g:center>
<!-- Pager. -->
<g:south
size="3">
<g:HTMLPanel>
<table
style="width:100%">
<tr>
<td
align='center'>
<c:SimplePager
ui:field='pager' />
</td>
</tr>
</table>
</g:HTMLPanel>
</g:south>
</g:DockLayoutPanel>
</ui:UiBinder>
You can wrap a DataGrid with SimplePager or whatever do you wish, and make a new "Widget" called "CDataGrid" (as you said) that not extends DataGrid but can extends Composite.
I hope I can give you a little help with this.
Best Regards,
iVieL.
It does integrate with DateGrid.
Take a look at the showcase for an example:
http://gwt.google.com/samples/Showcase/Showcase.html#!CwDataGrid
Adding pager as a part of the Grid, eliminates extra markup and steps in Compositve View. My solution was to create a new composite and provide callbacks.

How to customize look and feel of standard GWT components?

I have created GWT web application with standard Tree component from GWT. By default:
Tree
Implemented as a DIV containing nested TreeItems. The style name gwt-Tree applies to the DIV and the style overflow defaults to auto.
<div class="gwt-Tree" style="overflow: auto;">
<div style="position: relative; margin-left: 16;" (handle)>
<table>
<tr>
<td></td>
<td></td>
</tr>
</table>
</div>
Where is the place in GWT source code where I can change Tree rendering on my own design?
You should use CSS to style GWT components.
Here's a simple example using a UIBinder template:
<ui:style>
.myTree {
background-color: red;
}
</ui:style>
<g:HTMLPanel>
<g:Tree styleName="{style.myTree}" />
</g:HTMLPanel>
See this developer's guide also.

iframe scrolling on the iphone

I was aware of multiple scrolling libraries (TouchScroll, iScroll) for the iPhone/iOS due to its inability (???) to support overflow:scroll . However, I was not aware (and I am looking for confirmation) that IFRAMEs don't really work either. It appears that the iframe doesn't respect any attempt to give it a fixed size and always just resizes itself to its content. Am I correct on this? Is the only way to scroll an IFRAME to place it inside a block element with the overflow CSS property set and then to use a lib like the aforementioned?
simply adding...
overflow-y:auto;
-webkit-overflow-scrolling:touch;
to a div around my iframe worked for me
You can scroll any content which is set to overflow:auto by touching with two fingers and dragging. Don't put iFrame inside a div with overflow:auto, and instead set the iframe to overflow:auto itself. Unfortunately, iframe scrolling is very choppy, regardless of content or device, so the best solution is to find a way to make your content fit into one long page, with "top" & "bottom" view divs set to follow the viewport (if this is the effect you're going for.)
Have you given Joe Hewitt's Scrollability library a go?
You can read more about it here:
Scrollability, New iOS Physics Project from Facebook for iPhone Creator, Joe Hewitt
Hope this helps.
The code below works for me (thanks to Christopher Zimmermann for his blog post http://dev.magnolia-cms.com/blog/2012/05/strategies-for-the-iframe-on-the-ipad-problem/). The problems are:
1. There are no scroll bars to let the user know that they can scroll
2. Users have to use two-finger scrolling
3. The PDF files are not centered (still working on it)
<!DOCTYPE HTML>
<html>
<head>
<title>Testing iFrames on iPad</title>
<style>
div {
border: solid 1px green;
height:100px;
}
.scroller{
border:solid 1px #66AA66;
height: 400px;
width: 400px;
overflow: auto;
text-align:center;
}
</style>
</head>
<body>
<table>
<tr>
<td><div class="scroller">
<iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
</div>
</td>
<td><div class="scroller">
<iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
</div>
</td>
</tr>
<tr>
<td><div class="scroller">
<iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
</div>
</td>
<td><div class="scroller">
<iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
</div>
</td>
</tr>
</table>
<div> Here are some additional contents.</div>
</body>
</html>
Flippant answer: don't use IFRAMES anymore.

How to stop body background displaying between two tables in Iphone Safari

The following markup when viewed in Safari on Iphone and Ipad displays the body background color for 1 pixel between the two tables. What is this and how do I stop it?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body{
background:#000;
}
table{
background:#ffffff;
width:50px;
border:0;
margin:0;
padding:0;
}
</style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>a</td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>b</td>
</tr>
</table>
</body>
</html>
I've taken the liberty of dumping your markup to a file on my server:
Original markup
Alternative markup
There is no actual gap on my iPhone, but... the resizing algorithm does leave some space between the tables from time to time while zooming in/out.
This almost certainly has to do with some math not perfectly aligning to the pixel and getting rounded to match the nearest horizontal line. There is not much you can realy do about this, unless you resort to surrounding the tables with an inline-block that has the same background-color set like in the alternate file linked above.
On my iPhone the alternate version never displays any black lines between the tables. Be aware though that now the next element will be next to the inline-blocked div instead of underneath the tables. I'll leave solving that upto the reader. hint: css clear attribute.
Humm.. Have you updated Safari?
On Safari 5 I have no issue with this html...

Trying to get UIBinder to give me a span not a div

I am building a widget with UiBinder, and I need to have it enclosed in a <span /> but UiBinder only gives me <div />. E.g. <g:HTMLPanel /> => <div />. HorizonPanel, FlowPanel, VerticalPanel also give out only <div />.
Does any one know a solution?
Try this:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:HTMLPanel tag="span">
<!-- your stuff -->
</g:HTMLPanel>
</ui:UiBinder>
You can keep using a <div> but just add display: inline to its CSS, which will make it display as though it were a <span>.
Edit: fixed place at the end where I said 'div' but meant 'span'.
With regards to the answer above by Robert (sorry I can't figure out how to comment that directly)
This won't work out of the box, as widgets can't be placed inside plain HTML (the compiler will give you "error: found widget in html context"). But there's a simple workaround:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:HTMLPanel>
<span>
<!-- Your content with widgets goes here -->
</span>
</g:HTMLPanel>
</ui:UiBinder>
One other useful thing to mention is InlineHTML and InlineLabel widgets capable of holding arbitary html or plain text respectively in a <span>