×
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
hamishwillee (Talk | contribs)
m (Hamishwillee - Tidy wiki text)
hamishwillee (Talk | contribs)
m (Hamishwillee - Bot update - Fix metadata etc)
 
Line 1: Line 1:
 
[[Category:Code Examples]][[Category:Symbian Web Runtime]][[Category:Mobile Design]][[Category:How To]]
 
[[Category:Code Examples]][[Category:Symbian Web Runtime]][[Category:Mobile Design]][[Category:How To]]
{{ArticleMetaData <!-- v1.1 -->
+
{{ArticleMetaData <!-- v1.2 -->
|sourcecode= [[Media:WRTLayoutHeaderAndButtons_JSandCSS.zip]] [[Media:WRTLayoutHeaderAndButtons.zip]] [[Media:WRTLayoutHeaderAndButtons_JSandCSS.zip]]  
+
|sourcecode= [[Media:WRTLayoutHeaderAndButtons JSandCSS.zip]] [[Media:WRTLayoutHeaderAndButtons.zip]] [[Media:WRTLayoutHeaderAndButtons JSandCSS.zip]]
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|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'') -->
 
|devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') -->
Line 11: Line 11:
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|keywords= <!-- APIs, classes and methods (e.g. QSystemScreenSaver, QList, CBase -->
 
|keywords= <!-- APIs, classes and methods (e.g. QSystemScreenSaver, QList, CBase -->
|id= <!-- Article Id (Knowledge base articles only) -->
 
 
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 
|translated-by= <!-- [[User:XXXX]] -->
 
|translated-by= <!-- [[User:XXXX]] -->
Line 40: Line 39:
 
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==
Line 318: Line 317:
 
==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 391: 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.
83 page views in the last 30 days.
×