UI Layout Tips & FAQ

This page is a collection of miscellaneous tips and tricks for UI Layout. Many are based on questions asked by users.

Open All Sections   Close All Sections


Integrating jQuery UI Widgets

Many users ask about using various UI widgets with Layout, so this section brings together all information related to this.

UI Widgets Discussed Here

Two topics come up repeatedly in relation to using widgets with Layout: elements that 'popup' and element that 'resize'. Here is an overview of why this is:

Popup Elements

When you use UI Layout, it uses the DIVs in your markup to create 'panes', which become 'absolutely positioned containers' for the page content. Usually these layout-panes will have their overflow set to either 'hidden' or 'auto' (scroll). This makes it impossible for an element to escape the boundaries of the DIV. An element can only overlap the edges of its container if the container has: overflow: visible.

In addition, the originating pane must have a higher zIndex than the pane(s) being overlapped. NOTE that it is the relative zIndex of the panes that matter - not the zIndex of the popup element itself. An element's zIndex is only relevant within its container. Once it extends beyond the container's boundary, it is the container's zIndex that determines stack-order – ie, whether the element will be 'above' or 'beneath' the adjacent elements.

There are two ways to address the containment issue when using Layout:

The best way is for an element that needs to popup or move to be a child of 'body', instead of being a child of a 'pane'. This eliminates all containment issues since the element is not 'inside' the pane, and therefore not bound within its borders.

For elements that must be inside a pane, Layout provides utilities that can automatically or manually alter the pane's overflow setting and zIndex temporarily so that elements inside the pane can extend beyond its boundaries and appear 'above' the adjacent panes. The Simple Demo illustrates this with simple drop-down menus.

Resizable & Scrolling Elements

Some widgets use Javascript to adjust their size to their container - like the Accordion widget. Since Layout creates dynamically resizable regions, the widget's container can be resized or hidden. To keep the widget's size in sync with its container, a simple callback can be added to your layout:

$('body').layout(){
    center__onresize: function () {
        $('#Accordion').accordion('resize')
    }
});

Layout has callbacks for every event - both pre and post - so there are unlimited options for integrating widgets that require resizing, or that need to 'limit' what user are allowed to do. Layout events can be modifed or cancelled on the fly using callbacks like center__onresize_start.

UI Tabs

The tabs widget requires no special treatement if you only want its standard functionality.

However, Layout provides enhanced functionality for tabs simply by adding a single wrapper DIV. Here is the 'before' markup:

<DIV class="ui-layout-center">
    <UL>
        <LI><A href="#tabs-1">Tab 1</A></LI>
        <LI><A href="#tabs-2">Tab 2</A></LI>
        <LI><A href="#tabs-3">Tab 3</A></LI>
    </UL>
	<DIV id="tabs-1"></DIV>
	<DIV id="tabs-2"></DIV>
	<DIV id="tabs-3"></DIV>
</DIV>

And here it is with the extra wrapper DIV (ui-layout-content):

<DIV class="ui-layout-center">
    <UL>
        <LI><A href="#tabs-1">Tab 1</A></LI>
        <LI><A href="#tabs-2">Tab 2</A></LI>
        <LI><A href="#tabs-3">Tab 3</A></LI>
    </UL>
    <!-- add wrapper that Layout will auto-size to 'fill space' -->
    <DIV class="ui-layout-content">
        <DIV id="tabs-1"></DIV>
        <DIV id="tabs-2"></DIV>
        <DIV id="tabs-3"></DIV>
    </DIV>
</DIV>

The wrapper div makes the 'tabs' stay in place, so only the 'tab-panels' scroll. This is exactly how tabs normally work in a desktop UI, and it is accomplished without any extra Javascript or CSS – Layout handles it automatically.

See the Tabs Demo for examples.

This tab demo shows a Layout Inside a Tab.

UI Accordion

The tabs widget requires no special treatement if you only want its standard functionality. However the Accordion widget works best with Layout when you use the 'fillSpace' option, which makes the accordion auto-size to fill its container. This is how accordions normally appear in applications.

The Accordion widget uses Javascipt to set its height - not CSS. This means that if the widget's container is resized, the accordion must be manually resized by calling its resize() method. Layout triggers a callback method whenever a pane resizes, so this is easily integrated with an accordion...

$('body').layout(){
    center__onresize: function () {
        $('#Accordion').accordion('resize')
    }
});

See the Accordion Demo.

UI Draggables

Draggable elements are contrained by their containers (unless overflow=visible). However, an element that is a child of the 'body' can overlay all other elements on the page.

The draggables widget has a 'helper' option that allows you to clone the draggable element, and append this clone to the page body. This avoids the containment/overflow issue completely, since the element being dragged is no longer inside any layout pane.

Here is sample code to accomplish this. (slightly different than for the sortable widget)

$(".myDraggables").draggable({ 
   // create a clone & append it to 'body' 
   helper: function (e,ui) {
      return $(this).clone().appendTo('body').css('zIndex',5).show();
   } 
}) 

SEE the Droppable Between Panes demo

If you simply want to 'drag' the original element anywhere on the page, the simplest solution is to not put the element inside a pane - make it a child of the BODY instead, with a zIndex of 5. This will make it float over top of the Layout - completely independant of it. If you need more control over the draggable, I recommend using a droppable target. You could make an entire 'pane' a droppable target, which would provide a 'drop' event you can use to run your own custom code.

For general information on dragging elements between layout-panes, see the Draggable Elements tip below.

UI Droppables

The droppables widget is always used with draggable elements. As long your draggables use the helper noted above, the droppable does not require anything special

$(".myDroppables").droppable({ 
   accept: '.myDraggables'
}) 

SEE the Droppable Between Panes demo

UI Sortables

The sortables widget has a 'helper' option that allows you to clone the draggable element, and append this clone to the page body. This avoids the containment/overflow issue completely, since the element being dragged is no longer inside any layout pane.

Here is sample code to accomplish this. (slightly different than for the draggable widget)

$(".mySortables").sortable({ 
   // create a clone & append it to 'body' 
   helper: function (e,ui) {
      return $(ui).clone().appendTo('body').show();
   } 
}) 

SEE the Droppable Between Panes demo

UI Date-Picker

The Date-Picker widgets auto-generates elements to create a popup calendar. These elements are appended to the page body, as they should be. However, by default no zIndex is applied, therefore the popup calendar appears 'under' the layout-panes instead of 'above' as a popup needs to be.

So when using the Date-Picker widget with Layout, add this CSS rule...

#ui-datepicker-div {
    /* Minimum of '5' is required */
    z-index: 5;
}

SEE the Date-Picker demo.

UI Dialog

Dialogs require no special effort with Layout - they just work. Plus, you can put a layout inside your dialog.

SEE the Dialog demo.

Menu Widgets

There is no official UI Menu widget yet, but it is included here because it is a common need, and will probably be part of the next UI release.

Dropdown Menus and Popup Menus often need to overlap adjacent panes. The ideal solution is to append the menu elements to the 'body', in which case no additional effort is needed to use the menus with Layout. When this is not practical, you have two options for handling menus:

  1. If the menu appear only in a single, non-scrolling layout-pane, and you are not using resizer-bars in your layout, then just give that pane: overflow: visible – and ensure it is the last pane in the HTML markup. By making it last, it has a naturally higher stack-order.
  2. In all other cases, use Layout's built-in utility: allowOverflow(). This can be triggered many different ways, including from the code that opens your menu.

SEE menu samples in the Simple demo. Various methods of triggering allowOverflow are used - view the page source.

SEE the documentation for more information: Working with Drop-Downs and Pop-Ups.

Toolbar Widgets

There is no official UI Toolbar widget yet, but it is included here because it is a common need, and will probably be part of the next UI release.

Toolbars work exceptionally well with Layout, and do not require any special treatment. Every aspect of a layout can be controlled with simple Javascript commands, so it is very easy to use toolbar buttons to trigger layout events. For example, a "Help" button can toggle a help-panel to slide open/closed.

To make it even easier, utilities are provided that automate the binding of Layout commands to buttons, images or any clickable elements. These methods can also keep buttons in sync with the layout, and add special classes you can use with you CSS to customize buttons to show their 'state'. For example, it is easy to create a 'pin-button' that displays 'pin-up' or 'pin-down' depending on whether the bound pane is open or closed. This replicates the functionality of a standard desktop UI.

SEE the Complex Demo for samples of Toolbar and Pin buttons.

SEE the documentation for more information: Creating Custom Toggler Buttons.

Other/Future Widgets

Widgets that do not popup or move outside their container should work with Layout with any special treatment. These include:

Widgets that 'popup' over-top of adjacent content may require handling similar to that for menus, draggables or date-pickers. If the widget is well designed, a simple option or CSS rule should handle it. But even if the widget does not provide a built-in solution, Layout's allowOverflow utility can be used to make it work. Examples of 'popup widgets' coming in the future include:

If you have trouble integrating any UI widget with Layout, post your problem in the Discussion Forum – preferably with a sample page. Layout is very versatile so a solution can usually be found fairly quickly.

Draggable Elements

Q: How can I drag & drop elements between panes?

An element inside a layout-pane is 'contained' by that pane. For the element to be visible beyond the pane's boundaries, two things must be true:

There are two utility methods created for this purpose.

See Working with Drop-Downs and Popups for more information.

There is a BETTER SOLUTION when using jQuery UI widgets...

For information specific to the UI Draggable, Droppable & Sortable widgets, see the Draggables, Droppables & Sortables tip.

Control Pane Scrolling

Q: Is there a way to disable scrolling in a pane?

Normally all 'pane' elements have no overflow specified, so they display as: 'overflow: visible'

To make a pane scroll, use 'overflow: auto'

To hide any overflow, use 'overflow: hidden'

If you have the applyDefaultStyles option enabled, then all panes are set: 'overflow: auto'. In this case, to disable scrolling you must 'override' the default style using !important

// disable scrolling in ALL panes
.ui-layout-pane {
    overflow: hidden !important;
}

// disable scrolling only in the North & South panes
.ui-layout-pane-north ,
.ui-layout-pane-south {
    overflow: hidden !important;
}

State Management

Q: Is it possible to save the current state in a cookie, so that UI customization is kept across sessions?

UPDATED April 22, 2009

Saving state is not built into Layout (yet), but a tool is available. See this demo:

This state management implementation requires these supporting files:

EXAMPLE

To activate state management, bind layoutState.save() to window.unload(), and then load() the saved state when creating your layout. Here's an example:

<SCRIPT>

// bind save() to window.onunload
$(window).unload(function(){ layoutState.save('myLayout') }); 

// DEFAULT LAYOUT SETTINGS
var myDefaultSettings = {
    initClosed: true
,   west__size: 150
,   east__size: 150
}

var myLayout; // create global var for the layout-instance object

$(document).ready( function() {
    // load & used 'saved-state' to override defaults
    myLayout = $("body").layout(
        $.extend( myDefaultSettings, layoutState.load('myLayout') )
    );
});

</SCRIPT>

By default, layoutState will save pane-size, and whether it is 'closed' or 'hidden'. You can choose which panes and 'states' you want to manage two ways. Either modify the 'keys' param so the cookie saves only what you want (recommended), or utilize only the specific keys you want out of the hash returned by load().

You can modify the 'keys' option, and cookie options like 'expires', either by setting your preferences as 'defaults', or by passing custom options when you call the methods. Here is an example of both:

<SCRIPT>

// set defaults so don't have to repeat them
layoutState.options.layoutName = "myLayoutName";
layoutState.options.expires = 30; // 30-day cookie
// keys in sub-key-format
layoutState.options.keys = "west.size,west.isClosed";
// OR keys in flat-format
layoutState.options.keys = "west__size,west__isClosed";

// now you don't have to specify a layoutName...
$(window).unload( layoutState.save );
$.extend( myDefaultSettings, layoutState.load() )

// OR you can pass different options each time
layoutState.save(
    "myLayoutName" // layout/cookie name
,   "west.size,west.isClosed" // list of keys
,   { expires: 30 } // hash of other options
);

</SCRIPT>

IMPORTANT: Specify the 'keys' for state management in the same format as your default settings:

Normally you should set the default options, unless there are multiple layouts on the page. In this case, you must pass at least the layoutName for the 2nd and 3rd layouts. But you could still set default/common options for values like 'keys', 'expires', 'domain', etc.

NOTE: layoutState creates a cookie with the name you provide for the layout (eg, "myLayout"). So you can save multiple layout configurations as long as each layout has a different name. If desired, customize the cookie options (domain & path) to control where the cookie it used. For normal use though, the default options are fine.

layoutState Properties

The layoutState function has two property keys:

layoutState Methods

The layoutState function is only temporary - until integrated into UI Layout - so there is no documentation for it. But it is simple and only has 3 methods:

Looking at the demo page and the layoutState function should be all you need, but if you have trouble, use the Discussion forum for assistance.

State Data Vars

Normally you will care about only a few vars when saving the layout-state. Here is how saved state-data correlates to the 'options' used to initialize a layout:

The layoutState function saves the state so that it is ready for use onLoad. So if the west pane is 'closed' (state.west.isClosed), this is saved in the cookie as: 'west.initClosed=true' (OR west__initClosed=true).

For reference, here are all the state-values each 'border-pane' has:

Other data is saved in the state object, like 'minPosition', but this is for internal use only.

In the future, state will also store a complete set of dimensions for ALL panes.

State-management for UI Layout has unlimited options - you can persist anything you want. So plan which layouts/panes/states you want to persist and which should always return to defaults, then customize the 'keys' option(s) accordingly.

 


Open All Sections   Close All Sections