×
Namespaces

Variants
Actions
(Difference between revisions)

How to build a Web Runtime layout with Header and Buttons Bar

From Nokia Developer Wiki
Jump to: navigation, search
jappit (Talk | contribs)
(Categories added)
hamishwillee (Talk | contribs)
m (Hamishwillee - Bot update - Fix metadata etc)
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Code Examples]][[Category:Web Runtime (WRT)]][[Category:Mobile_Design]][[Category:How To]]
+
[[Category:Code Examples]][[Category:Symbian Web Runtime]][[Category:Mobile Design]][[Category:How To]]
 +
{{ArticleMetaData <!-- v1.2 -->
 +
|sourcecode= [[Media:WRTLayoutHeaderAndButtons JSandCSS.zip]] [[Media:WRTLayoutHeaderAndButtons.zip]] [[Media:WRTLayoutHeaderAndButtons JSandCSS.zip]]
 +
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 +
|devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') -->
 +
|sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Qt SDK 1.1.4]) -->
 +
|platform= <!-- Compatible platforms - e.g. Symbian^1 and later, Qt 4.6 and later -->
 +
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 +
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
 +
|signing= <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 +
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 +
|keywords= <!-- APIs, classes and methods (e.g. QSystemScreenSaver, QList, CBase -->
 +
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 +
|translated-by= <!-- [[User:XXXX]] -->
 +
|translated-from-title= <!-- Title only -->
 +
|translated-from-id= <!-- Id of translated revision -->
 +
|review-by= <!-- After re-review: [[User:username]] -->
 +
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 +
|update-by= <!-- After significant update: [[User:username]]-->
 +
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 +
|creationdate= 20090616
 +
|author= [[User:Jappit]]
 +
}}
 +
 
 
==Description==
 
==Description==
This article explains '''how to build from scratch a layout for Web Runtime widgets''' with these '''UI features''':
+
This article explains how to build from scratch a layout for Web Runtime widgets with these UI features:
* a '''header bar''', that can contain the widget name and other optional elements
+
* a header bar, that can contain the widget name and other optional elements
* a '''central body''', containing the dynamic content of the widget
+
* a central body, containing the dynamic content of the widget
* a '''buttons' toolbar'''
+
* a buttons' toolbar
  
Also, the built layout will support the following '''functionalities''':
+
Also, the built layout will support the following functionalities:
* '''unified method to add buttons or softkeys''', depending on the widget needs (e.g.: based on device's display resolution)
+
* unified method to add buttons or softkeys, depending on the widget needs (e.g.: based on device's display resolution)
* '''support for display rotations'''
+
* support for display rotations
* '''repositioning of buttons' toolbar''' depending on display orientation
+
* repositioning of buttons' toolbar depending on display orientation
* support for '''easy switching''' of the widget main view
+
* support for easy switching of the widget main view
* automatic '''support for scrolling'''
+
* automatic support for scrolling
  
 
==Sample layouts==
 
==Sample layouts==
The following pictures shows '''how the layout appears in portrait and landscape mode''':<br/>
+
The following pictures shows how the layout appears in portrait and landscape mode:<br/>
'''Portrait mode'''<br/>
+
Portrait mode<br/>
[[Image:Wrtlayout_headerbuttons_p.png]]<br/>
+
[[File:Wrtlayout headerbuttons p.png]]<br/>
'''Landscape mode'''<br/>
+
Landscape mode<br/>
[[Image:Wrtlayout_headerbuttons_l.png]]<br/>
+
[[File:Wrtlayout headerbuttons l.png]]<br/>
  
 
==Implementation==
 
==Implementation==
 
===The layout HTML structure===
 
===The layout HTML structure===
The layout is structured into these '''main DOM elements''':
+
The layout is structured into these main DOM elements:
* a '''DIV element for the header'''
+
* a DIV element for the header
* a '''DIV element for the widget content'''
+
* a DIV element for the widget content
* '''2 DIV elements for the buttons' toolbar''', that will be used depending on the display orientation
+
* 2 DIV elements for the buttons' toolbar, that will be used depending on the display orientation
 
The basic layout structure is the following:
 
The basic layout structure is the following:
 
<code html4strict>
 
<code html4strict>
Line 52: Line 75:
 
</html>
 
</html>
 
</code>
 
</code>
The DIV element with '''toolbar_buttons''' id is a placeholder element for the toolbars' buttons.
+
The DIV element with toolbar_buttons id is a placeholder element for the toolbars' buttons.
 
===The basic CSS code===
 
===The basic CSS code===
In order to properly layout the various interface elements, very '''few basic CSS rules''' are needed:
+
In order to properly layout the various interface elements, very few basic CSS rules are needed:
 
<code css>
 
<code css>
 
#right_toolbar
 
#right_toolbar
Line 66: Line 89:
 
</code>
 
</code>
 
Things to note in the above CSS code:
 
Things to note in the above CSS code:
* the '''right_toolbar''' is set to '''float: right''', in order '''to have the toolbar, on landscape displays, on the right side of the widget'''. In order to have it on the left side, it is enough to change the float property to left.
+
* the {{Icode|right_toolbar}} is set to float: right, in order to have the toolbar, on landscape displays, on the right side of the widget. In order to have it on the left side, it is enough to change the float property to left.
An '''alternative approach''' to have the buttons' toolbar differently placed depending on the display orientation, '''based on absolute positioning''', is visible in the '''STEW widget''', and is explained in details here: [http://library.forum.nokia.com/index.jsp?topic=/Web_Developers_Library/GUID-B12990B6-979C-4BBA-B030-FB7CEC04CB3A.html STEW: supporting screen rotation]
+
An alternative approach to have the buttons' toolbar differently placed depending on the display orientation, based on absolute positioning, is visible in the STEW widget, and is explained in details here: [http://library.developer.nokia.com/index.jsp?topic=/Web_Developers_Library/GUID-B12990B6-979C-4BBA-B030-FB7CEC04CB3A.html STEW: supporting screen rotation]
* the '''overflow-y: auto''' property for the '''screen_container''' allow to support '''vertical scrolling for views''' that are higher than the available space.
+
* the {{Icode|overflow-y: auto}} property for the {{Icode|screen_container}} allow to support vertical scrolling for views that are higher than the available space.
  
 
===The JavaScript code===
 
===The JavaScript code===
All the widget layout is managed through a '''layout JavaScript object''', that will be defined and implemented in this section. This object takes care of '''layout appearance, events management, and view switching'''.
+
All the widget layout is managed through a layout JavaScript object, that will be defined and implemented in this section. This object takes care of layout appearance, events management, and view switching.
 
====The layout properties====
 
====The layout properties====
First, some '''properties''' are set in order to control the '''layout behavior and appearance'''.
+
First, some properties are set in order to control the layout behavior and appearance.
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 96: Line 119:
 
</code>
 
</code>
 
====Buttons/SoftKeys generation====
 
====Buttons/SoftKeys generation====
Depending on the '''useSoftkeys''' property value, the layout will '''generate and handle softkey menu items or toolbar buttons''', that will be inserted in the '''toolbar_buttons''' placeholder DIV element. In order to do this, the following '''addMainOption()''' method is defined:
+
Depending on the {{Icode|useSoftkeys}} property value, the layout will generate and handle softkey menu items or toolbar buttons, that will be inserted in the {{Icode|toolbar_buttons}} placeholder DIV element. In order to do this, the following {{Icode|addMainOption()}} method is defined:
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 127: Line 150:
 
}
 
}
 
</code>
 
</code>
The three arguments passed to the '''addMainOption()''' method are:
+
The three arguments passed to the {{Icode|addMainOption()}} method are:
* the '''menu item/button label''',
+
* the menu item/button label,
* the '''menu item id''' (id is not used for toolbar buttons)
+
* the menu item id (id is not used for toolbar buttons)
* the '''handler function''' called on the select/click events
+
* the handler function called on the select/click events
 
====Laying out the layout elements====
 
====Laying out the layout elements====
 
First, a helper methods is defined in order to detect display orientation:
 
First, a helper methods is defined in order to detect display orientation:
Line 143: Line 166:
 
}
 
}
 
</code>
 
</code>
The layout object has to '''manage the widget's appearance''', and specifically has to perform these operations:
+
The layout object has to manage the widget's appearance, and specifically has to perform these operations:
* '''resize the various layout elements''' depending on the display size and orientation
+
* resize the various layout elements depending on the display size and orientation
* '''place the toolbar buttons''' (if not using softkeys) according to the display orientation
+
* place the toolbar buttons (if not using softkeys) according to the display orientation
All these operations are managed by the following '''setupInterface()''' method:
+
All these operations are managed by the following setupInterface() method:
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 190: Line 213:
 
</code>
 
</code>
 
====Managing display rotations====
 
====Managing display rotations====
'''When the display changes orientation''', the interface needs to be relayed out, in order to '''resize and move elements appropriately'''. Since all these things are performed by the setupInterface() method, the following '''onResize()''' method will uniquely call this method:
+
When the display changes orientation, the interface needs to be relayed out, in order to resize and move elements appropriately. Since all these things are performed by the {{Icode|setupInterface()}} method, the following {{Icode|onResize()}} method will uniquely call this method:
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 203: Line 226:
 
</code>
 
</code>
 
====Setting the widget main view====
 
====Setting the widget main view====
In order to '''easily change the main view of the widget''', the '''gotoScreen()''' is defined, that will hide the currently visible view, and show the new one.
+
In order to easily change the main view of the widget, the {{Icode|gotoScreen()}} is defined, that will hide the currently visible view, and show the new one.
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 227: Line 250:
 
</code>
 
</code>
 
====Initializing layout and events====
 
====Initializing layout and events====
Now, '''all is ready to be initialized and used'''. So, it is possible to define an '''init()''' method that will take care of:
+
Now, all is ready to be initialized and used. So, it is possible to define an {{Icode|init()}} method that will take care of:
* '''calling methods for layout initialization'''
+
* calling methods for layout initialization
* '''setting up event handlers''' for widget resize events
+
* setting up event handlers for widget resize events
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 255: Line 278:
 
</code>
 
</code>
 
====Polling for display rotations====
 
====Polling for display rotations====
'''Some devices''', as explained [http://library.forum.nokia.com/topic/Web_Developers_Library/GUID-B12990B6-979C-4BBA-B030-FB7CEC04CB3A.html here], '''do not support the 'onResize' event'''. So, the approach defined in the linked Forum Nokia Library page is implemented, in order to correctly manage display resize events also on these devices.
+
Some devices, as explained [http://www.developer.nokia.com/Resources/Library/Web/ here], do not support the 'onResize' event. So, the approach defined in the linked Nokia Developer Library page is implemented, in order to correctly manage display resize events also on these devices.
The following '''pollResize()''' method is defined:
+
The following {{Icode|pollResize()}} method is defined:
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 271: Line 294:
 
}
 
}
 
</code>
 
</code>
And is '''scheduled to be periodically called''' by the '''init()''' method, that is modified as follows:
+
And is scheduled to be periodically called by the init() method, that is modified as follows:
 
<code javascript>
 
<code javascript>
 
var layout =  
 
var layout =  
Line 293: Line 316:
 
</code>
 
</code>
 
==Layout object: how to use it==
 
==Layout object: how to use it==
Usage of the '''layout''' object is quite straightforward, and requires these steps:
+
Usage of the layout object is quite straightforward, and requires these steps:
* '''import the layout JavaScript and CSS files''' (available here: [[Media:WRTLayoutHeaderAndButtons_JSandCSS.zip]]
+
* import the layout JavaScript and CSS files (available here: [[Media:WRTLayoutHeaderAndButtons JSandCSS.zip]]
 
) in your widget's HTML code:  
 
) in your widget's HTML code:  
 
<code html4strict>
 
<code html4strict>
Line 306: Line 329:
 
</html>
 
</html>
 
</code>
 
</code>
* '''define the basic HTML structure''', as defined in the above section, and complete them with your widget specific code. An example of widget HTML code with 3 main views is the following:
+
* define the basic HTML structure, as defined in the above section, and complete them with your widget specific code. An example of widget HTML code with 3 main views is the following:
 
<code html4strict>
 
<code html4strict>
 
<html>
 
<html>
Line 349: Line 372:
 
</html>
 
</html>
 
</code>
 
</code>
* then, the '''layout can be initialized''', by '''adding the desired softkeys/buttons''' and by calling its initialization method.
+
* then, the layout can be initialized, by adding the desired softkeys/buttons and by calling its initialization method.
 
<code javascript>
 
<code javascript>
 
function init()
 
function init()
Line 367: Line 390:
 
The following related files are available for download:
 
The following related files are available for download:
 
* A sample widget using the layout implemented in this article: [[Media:WRTLayoutHeaderAndButtons.zip]]
 
* A sample widget using the layout implemented in this article: [[Media:WRTLayoutHeaderAndButtons.zip]]
* The layout JavaScript and CSS files: [[Media:WRTLayoutHeaderAndButtons_JSandCSS.zip]]
+
* The layout JavaScript and CSS files: [[Media:WRTLayoutHeaderAndButtons JSandCSS.zip]]

Latest revision as of 08:21, 7 May 2012

Article Metadata
Code ExampleArticle
Created: jappit (16 Jun 2009)
Last edited: hamishwillee (07 May 2012)

Contents

[edit] Description

This article explains how to build from scratch a layout for Web Runtime widgets with these UI features:

  • a header bar, that can contain the widget name and other optional elements
  • a central body, containing the dynamic content of the widget
  • a buttons' toolbar

Also, the built layout will support the following functionalities:

  • unified method to add buttons or softkeys, depending on the widget needs (e.g.: based on device's display resolution)
  • support for display rotations
  • repositioning of buttons' toolbar depending on display orientation
  • support for easy switching of the widget main view
  • automatic support for scrolling

[edit] Sample layouts

The following pictures shows how the layout appears in portrait and landscape mode:
Portrait mode
Wrtlayout headerbuttons p.png
Landscape mode
Wrtlayout headerbuttons l.png

[edit] Implementation

[edit] The layout HTML structure

The layout is structured into these main DOM elements:

  • a DIV element for the header
  • a DIV element for the widget content
  • 2 DIV elements for the buttons' toolbar, that will be used depending on the display orientation

The basic layout structure is the following:

<html>
<body>
 
<div id="header">
 
</div>
 
<div id="right_toolbar">
 
</div>
 
<div id="screen_container">
 
</div>
 
<div id="bottom_toolbar">
<div id="toolbar_buttons">
</div>
</div>
 
 
</body>
</html>

The DIV element with toolbar_buttons id is a placeholder element for the toolbars' buttons.

[edit] The basic CSS code

In order to properly layout the various interface elements, very few basic CSS rules are needed:

#right_toolbar
{
float:right;
}
#screen_container
{
overflow-y:auto;
}

Things to note in the above CSS code:

  • the right_toolbar is set to float: right, in order to have the toolbar, on landscape displays, on the right side of the widget. In order to have it on the left side, it is enough to change the float property to left.

An alternative approach to have the buttons' toolbar differently placed depending on the display orientation, based on absolute positioning, is visible in the STEW widget, and is explained in details here: STEW: supporting screen rotation

  • the overflow-y: auto property for the screen_container allow to support vertical scrolling for views that are higher than the available space.

[edit] The JavaScript code

All the widget layout is managed through a layout JavaScript object, that will be defined and implemented in this section. This object takes care of layout appearance, events management, and view switching.

[edit] The layout properties

First, some properties are set in order to control the layout behavior and appearance.

var layout = 
{
/* true if the layout must use softkeys
* false if the layout must use toolbar buttons
*/

useSoftkeys: false,
 
/* CSS class applied to the buttons' toolbar */
toolbarButtonCssClass: 'toolbar_button',
 
/* value of the last detected display width */
lastDetectedWidth: 0,
 
/* value of the last detected display height */
lastDetectedHeight: 0,
 
/* holds a reference to the currently displayed view */
currentScreen: null
}

[edit] Buttons/SoftKeys generation

Depending on the useSoftkeys property value, the layout will generate and handle softkey menu items or toolbar buttons, that will be inserted in the toolbar_buttons placeholder DIV element. In order to do this, the following addMainOption() method is defined:

var layout = 
{
[...]
 
addMainOption: function(text, id, handler)
{
if(this.useSoftkeys)
{
var item = new MenuItem(text, id);
 
item.onSelect = handler;
 
menu.append(item);
}
else
{
var button = document.createElement('div');
 
button.className = this.toolbarButtonCssClass;
 
button.appendChild(document.createTextNode(text));
 
button.onclick = handler;
 
document.getElementById('toolbar_buttons').appendChild(button);
}
},
}

The three arguments passed to the addMainOption() method are:

  • the menu item/button label,
  • the menu item id (id is not used for toolbar buttons)
  • the handler function called on the select/click events

[edit] Laying out the layout elements

First, a helper methods is defined in order to detect display orientation:

var layout = 
{
[...]
 
isLandscape: function()
{
return window.innerWidth > window.innerHeight;
}

The layout object has to manage the widget's appearance, and specifically has to perform these operations:

  • resize the various layout elements depending on the display size and orientation
  • place the toolbar buttons (if not using softkeys) according to the display orientation

All these operations are managed by the following setupInterface() method:

var layout = 
{
[...]
 
setupInterface: function()
{
if(!this.useSoftkeys)
menu.hideSoftkeys();
 
this.lastDetectedWidth = window.innerWidth;
this.lastDetectedHeight = window.innerHeight;
 
if(this.useSoftkeys)
{
document.getElementById('screen_container').style.height =
(this.lastDetectedHeight - document.getElementById('header').offsetHeight) + 'px';
}
else if(this.isLandscape())
{
document.getElementById('bottom_toolbar').style.display = 'none';
document.getElementById('right_toolbar').style.display = '';
document.getElementById('right_toolbar').appendChild(document.getElementById('toolbar_buttons'));
 
document.getElementById('right_toolbar').style.height =
(this.lastDetectedHeight - document.getElementById('header').offsetHeight) + 'px';
 
document.getElementById('screen_container').style.height =
(this.lastDetectedHeight - document.getElementById('header').offsetHeight) + 'px';
}
else
{
document.getElementById('bottom_toolbar').style.display = '';
document.getElementById('right_toolbar').style.display = 'none';
document.getElementById('bottom_toolbar').appendChild(document.getElementById('toolbar_buttons'));
 
document.getElementById('screen_container').style.height =
(this.lastDetectedHeight - document.getElementById('header').offsetHeight - document.getElementById('toolbar_buttons').offsetHeight) + 'px';
}
}
}

[edit] Managing display rotations

When the display changes orientation, the interface needs to be relayed out, in order to resize and move elements appropriately. Since all these things are performed by the setupInterface() method, the following onResize() method will uniquely call this method:

var layout = 
{
[...]
 
onResize: function()
{
this.setupInterface();
},
}

[edit] Setting the widget main view

In order to easily change the main view of the widget, the gotoScreen() is defined, that will hide the currently visible view, and show the new one.

var layout = 
{
[...]
 
gotoScreen: function(screenId, clearHistory)
{
var newScreen = document.getElementById(screenId);
 
if(newScreen)
{
if(this.currentScreen != null)
{
this.currentScreen.style.display = 'none';
}
this.currentScreen = newScreen;
 
this.currentScreen.style.display = '';
}
}
}

[edit] Initializing layout and events

Now, all is ready to be initialized and used. So, it is possible to define an init() method that will take care of:

  • calling methods for layout initialization
  • setting up event handlers for widget resize events
var layout = 
{
[...]
 
init: function(startScreen)
{
this.setupInterface();
 
var self = this;
 
window.addEventListener(
'resize',
function()
{
self.onResize();
},
false
);
 
this.gotoScreen(startScreen);
}
}

[edit] Polling for display rotations

Some devices, as explained here, do not support the 'onResize' event. So, the approach defined in the linked Nokia Developer Library page is implemented, in order to correctly manage display resize events also on these devices. The following pollResize() method is defined:

var layout = 
{
[...]
 
pollResize: function()
{
if(window.innerWidth != this.lastDetectedWidth || window.innerHeight != this.lastDetectedHeight)
{
this.onResize();
}
}
}

And is scheduled to be periodically called by the init() method, that is modified as follows:

var layout = 
{
[...]
 
init: function(startScreen)
{
[...]
 
setInterval(
function()
{
self.pollResize();
}
,
1000
);
}
}

[edit] Layout object: how to use it

Usage of the layout object is quite straightforward, and requires these steps:

) in your widget's HTML code:

<html>
<head>
<script language="javascript" type="text/javascript" src="layout.js"></script>
<link rel="stylesheet" href="layout.css" type="text/css">
</head>
 
[...]
</html>
  • define the basic HTML structure, as defined in the above section, and complete them with your widget specific code. An example of widget HTML code with 3 main views is the following:
<html>
[...]
 
<body onLoad="javascript:init();">
 
 
 
<div id="header">
Widget Layout sample
</div>
 
<div id="right_toolbar">
</div>
 
<div id="screen_container">
 
<div class="screen" id="screen_home" style="display: none;">
<strong>Widget Layout with Header and Buttons' Toolbar</strong>
</div>
 
<div class="screen" id="screen_info" style="display: none;">
<h2>Widget Info</h2>
 
Some infos about the application
</div>
 
<div class="screen" id="screen_more" style="display: none;">
Some more info...
</div>
</div>
 
<div id="bottom_toolbar">
<div id="toolbar_buttons">
 
</div>
</div>
 
 
</body>
</html>
  • then, the layout can be initialized, by adding the desired softkeys/buttons and by calling its initialization method.
function init()
{
layout.useSoftkeys = false;
 
layout.addMainOption('Home', 1001, function(){layout.gotoScreen("screen_home");})
layout.addMainOption('Info', 1002, function(){layout.gotoScreen("screen_info");})
layout.addMainOption('More', 1003, function(){layout.gotoScreen("screen_more");})
 
layout.init('screen_home');
}

So this example layout does not use softkeys: 3 buttons are so created, and each of them brings to a view defined in the above HTML code. Screenshots of the sample widget are visible at the beginning of this article.

[edit] Downloads

The following related files are available for download:

This page was last modified on 7 May 2012, at 08:21.
137 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×