Subscribe via Feed

Resizing an XPage Control with DHTML

Peter Presnell, Jun 19, 2010 3:09:00 PM

From time to time there is a need to design an XPage in which one section needs to fill the remaining screen real estate. Setting width to 100% and height to 100% does not always produce the desired result, especially across multiple browsers.  One solution to this need is to use DHTML to calculate the available height/width and assign the height/width to the appropriate components of the HTML.  Because browsers can be resized we need to perform this calculation when the page is first loaded as well as each time the page is resized. The following is an example of how I solved this need for one of my own XPage applications.

  1. I use the #{id:XPageControlID}' statement to resolve the HTML name of the ID that is being rendered on my browser.
  2. An inline statement such as document.getElementById('#{id:XPageContrilID}').style.height = document.body.clientHeight - offset + "px"; has the desired effect of setting the ids height via DHTML
  3. I can use the dojo function dojo.connect to add an event listener for the client side onresize event and pass an anonymous function that contains the code to resize one or more XPage controls.

Example

The following example also demonstrates the new onClientLoad event that is available in the current 8.5.2 beta to inject the JavaScript code and execute it when the XPage is loaded.  Being a beta release IBM may decide to remove this feature before the final release..


    document.getElementById('#{id:pagePanel}').style.width = document.body.clientWidth -250 + "px";
document.getElementById('#{id:Content}').style.width = document.body.clientWidth -250 + "px";
document.getElementById('#{id:ContentPanel}').style.width = document.body.clientWidth -250 + "px";
document.getElementById('#{id:Page}').style.height = document.body.clientHeight -72 + "px";
document.getElementById('#{id:Main}').style.height = document.body.clientHeight -72 + "px";
dojo.connect(window,"onresize",function(evt)
{
    document.getElementById('#{id:pagePanel}').style.height = document.body.clientHeight -72 + "px";
    document.getElementById('#{id:pagePanel}').style.width = document.body.clientWidth -250 + "px";
    document.getElementById('#{id:Content}').style.width = document.body.clientWidth -250 + "px";
    document.getElementById('#{id:ContentPanel}').style.width = document.body.clientWidth -250 + "px";
    document.getElementById('#{id:Page}').style.height = document.body.clientHeight -72 + "px";
    document.getElementById('#{id:Main}').style.height = document.body.clientHeight -72 + "px";
});]]>

 

Note: Thre is probably an OOP approach to this need that lifts all the JavaScript code off the XPage and places it a JavaScript library where it belongs, but I ams till working on that.



8 responses to Resizing an XPage Control with DHTML

Patrick Kwinten, June 21, 2010 11:36 AM

What Does “width: 100%” Do in CSS?

http://www.impressivewebs.com/width-100-percent-css/


Jeremy Hodge, June 20, 2010 1:53 PM

Hi Mike ... if you put the CSS from the first two examples I gave in my response, it will work ... I have several border apps working with border container, etc ... the key is the !important .. that will override the xsp.css definition and allow the border container to be displayed.


Mike McGarel, June 20, 2010 1:33 PM

I tried using the BorderContainer dijit a couple of weeks ago and found out it was broken in 8.5.1. To quote the ticket, ". . . BorderContainer displayed correctly in IE6, but cannot be viewed in IE7, IE8 and Firefox 3.5."

I heard that is is fixed in one of the 8.5.2 betas.


Peter Presnell, June 20, 2010 1:08 PM

Thx for the suggestions and offers of help. I probably read 40+ articles on this subject and tried all manner of combinations of nested divs with offsets and height/width settings but couldn't get them to work across the 4 browsers I am testing with. That doesn't mean there isn't a solution or I have given up on finding one -- just not now. Following the RAD process you sometimes have to think outside the square to find a solution, any solution. That was the idea behind the post. If you should find yourself in a position where your HTML/CSS is not delivering what you need then DHTML is an option. When I searched for information on this I found nothing in the XPage space to help me, so I decided to share my solution for the benefit of anyone who may follow.


Jeremy Hodge, June 20, 2010 11:50 AM

A couple of thoughts here ... if you want to do a 100% width/height div in XPages, you must have the following CSS defined on your page:

html, body {
width: 100% !important;
height: 100% !important;
overflow:auto important; // this one may be optional depending on what you have going on
}

Next, if you do have a border layout, or any other containers on your form that are fixed sizes, your 100% w/h div must not be in them ... best place to put it is just inside the body tag ... With XPages, everything you code (with one exception) gets put inside a form tag, so, depending how you style the form (if you do) you may also have to specify:

.xspForm {
width:100% !important;
height:100% Iimportant;
overflow:auto !important;
}

The reason is that as of 8.5.1 at least, the xsp.css defines the css for html, body, and form as:

height: inherit !important;
overflow: inherit !important;
width: inherit !important;

which can cause you issues if you don't override it.

Also, if you do have border containers, and you do put the div outside the border container so that it can cover the entire window, then the CSS to make that div 100% would be (this code also generally applies even if you don't use the containers as a good practice):

.hundyPCentDiv {
width: 100%;
height: 100%;
z-index: 1999; //party like its...
position: fixed; // all except for less than ie7
top: 0;
left: 0;
}

For < IE 7 the above will cause the 100% div to scroll with the body if the total height of the content exceeds the veiwport height, so you would have to apply some ie specific CSS to resolve that:

in your HTML:
<!--[if gte IE 5.5]>
<![if lt IE 7]>
<style type="text/css">
.hundyPCentDiv {
position: absolute;
left: expression( ( ( isJunk = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
top: expression( ( ( isAlsoJunk = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
}
</style>
<![endif]>
<![endif]-->

Its things like this that are why ie6 must go away, so try to make a conscious decision to not support ie6 in your apps if you can.


Simon O'Doherty, June 20, 2010 7:00 AM

Would not just changing the CSS class of the object achieve the same thing easier? Appears you had issues going that route. Can you expand on that? I would be interested to know.


Peter Presnell, June 20, 2010 12:39 AM

Hi Tim,
The example comes from an XPage that does have a BorderContainer dijit. I lost a great many hours with the HTML and CSS trying to get it to work before I decided to use the DHTML path as a way of keeping the project moving.


Tim Tripcony, June 19, 2010 7:26 PM

Peter, check out the BorderContainer dijit. This allows you to divide the content of the page into sections that automatically fill their designated container... and, it works the same across all major browsers. :)