You will usually create a dashboard panel following a banner notification posting as a reminder of the notification. Dashboards can also display ambient information or provide a dynamic window for background applications when you don’t need a full card stage. Although constrained by size and UI convention, dashboard summaries are fully functional stages, within which you can push scenes and employ any part of the Mojo API, though not all of the Mojo styles are available outside of card stages.
The full framework CSS is not automatically loaded when creating pop-up or dashboard stages. Currently, some of the styles that you can use in a card stage or main application window are not available within noncard stages. This will be addressed in time, but for now you may have to copy some style properties and selectors to your application CSS from the framework CSS.
Dashboards are constrained windows that span the full screen width and about 10% of the screen height in portrait mode; on the Palm Prē, that’s 320 pixels wide and 48 pixels high. But just as with card windows, you should lay out your dashboard windows to handle different widths for landscape modes or different screen sizes on future Palm webOS devices.
You can create a dashboard stage similar to the general stage example shown
earlier in this chapter, but you will declare it as a dashboard
stage type. We’ll add a dashboard
stage to News in updateFeedSuccess()
by following the banner notification with a call to createStageWithCallback()
, passing a
callback function that pushes dashboard-assistant.js with the feedlist and
the current feed index to post the feed’s title and the most recent new story headline. We’ll
also pass a global constant, News.DashboardStageName
, which defines
the dashboard stage name, set the lightweight
property to true
, and specify this as a
dashboard stage:
if (feedError == News.errorNone) { var appController = Mojo.Controller.getAppController(); var stageController = appController.getStageController(News.MainStageName); var dashboardStageController = appController.getStageProxy(News.DashboardStageName); // Post a notification if new stories and application is minimized if (this.list[this.feedIndex].newStoryCount > 0) { Mojo.Log.info("New Stories: ", this.list[this.feedIndex].title, " : ", this.list[this.feedIndex].newStoryCount, " New Items"); if (!Mojo.Controller.stageController.isActiveAndHasScenes() && News.notificationEnable) { var bannerParams = { // ** These next two lines are wrapped for book formatting only ** messageText: this.list[this.feedIndex].title+": "+this.list[this.feedIndex].newStoryCount+" New Items" }; appController.showBanner(bannerParams, {action: "notification", index: this.feedIndex}, this.list[this.feedIndex].url); // Create or update dashboard var feedlist = this.list; var selectedFeedIndex = this.feedIndex; if(!dashboardStageController) { Mojo.Log.info("New Dashboard Stage"); var pushDashboard = function(stageController){ stageController.pushScene("dashboard", feedlist, selectedFeedIndex); }; appController.createStageWithCallback({ name: News.DashboardStageName, lightweight: true }, pushDashboard, "dashboard"); } else { Mojo.Log.info("Existing Dashboard Stage"); dashboardStageController.delegateToSceneAssistant("updateDashboard", selectedFeedIndex); } } } } else { // There was a feed process error; unlikely, but could happen if the // feed was changed by the feed service. Log the error. if (feedError == News.invalidFeedError) { Mojo.Log.info("Feed ", this.nameModel.value, " is not a supported feed type."); } }
Before creating the stage, call getStageProxy(News.DashboardStageName)
. If the
stage exists, the proxy will be defined. Call the dashboard assistant’s
updateDashboard()
method with just the current feed index to use the existing dashboard
and update its contents with information about the latest feed
update.
Dashboard scenes have scene assistants and view templates since they are often dealing with dynamic data but are working within a restricted view. Use the same techniques described in the section Pop-up Notifications to render scenes and handle updates:
/* Dashboard Assistant - NEWS Copyright 2009 Palm, Inc. All rights reserved. Responsible for posting that last feed with new stories, including the new story count and the latest story headline. Arguments: - feedlist; News feed list - selectedFeedIndex; target feed Other than posting the new story, the dashboard will call the News apps handleLaunch with a "notification" action when the dashboard is tapped, and the dashboard window will be closed. */ function DashboardAssistant(feedlist, selectedFeedIndex) { this.list = feedlist; this.index = selectedFeedIndex; this.title = this.list[this.index].title; this.message = this.list[this.index].stories[0].title; this.count = this.list[this.index].newStoryCount; } DashboardAssistant.prototype.setup = function() { this.displayDashboard(this.title, this.message, this.count); this.switchHandler = this.launchMain.bindAsEventListener(this); this.controller.listen("dashboardinfo", Mojo.Event.tap, this.switchHandler); this.stageDocument = this.controller.stageController.document; this.activateStageHandler = this.activateStage.bindAsEventListener(this); Mojo.Event.listen(this.stageDocument, Mojo.Event.stageActivate, this.activateStageHandler); this.deactivateStageHandler = this.deactivateStage.bindAsEventListener(this); Mojo.Event.listen(this.stageDocument, Mojo.Event.stageDeactivate, this.deactivateStageHandler); }; DashboardAssistant.prototype.cleanup = function() { // Release event listeners this.controller.stopListening("dashboardinfo", Mojo.Event.tap, this.switchHandler); Mojo.Event.stopListening(this.stageDocument, Mojo.Event.stageActivate, this.activateStageHandler); Mojo.Event.stopListening(this.stageDocument, Mojo.Event.stageDeactivate, this.deactivateStageHandler); }; // Update scene contents, using render to insert the object into an HTML template DashboardAssistant.prototype.displayDashboard = function(title, message, count) { var info = {title: title, message: message, count: count}; var renderedInfo = Mojo.View.render({object: info, template: "dashboard/item-info"}); var infoElement = this.controller.get("dashboardinfo"); infoElement.innerHTML = renderedInfo; }; // Update dashboard scene contents - external method DashboardAssistant.prototype.updateDashboard = function(selectedFeedIndex) { this.index = selectedFeedIndex; this.title = this.list[this.index].title; this.message = this.list[this.index].stories[0].title; this.count = this.list[this.index].newStoryCount; this.displayDashboard(this.title, this.message, this.count); };
A conventional reminder dashboard is shown in Figure 10-3 with an icon on the left, a badge indicating the number of new stories, and the title and new story headline on the right.
All of the presentation for this dashboard is in the template, so the scene’s view file is minimal. Included in views/dashboard/dashboard-scene.html:
<div id="dashboardinfo" class="dashboardinfo"></div>
A template is defined in views/dashboard/item-info.html with the icon
container (palm-dashboard-icon-container
), the badge
(dashboard-new-item
and the custom
class dashboard-icon-news
), the title
area (dashboard-title
), and
the message area (dashboard-text
):
<div class="dashboard-notification-module"> <div class="palm-dashboard-icon-container"> <div class="dashboard-newitem"> <span>#{count}</span> </div> <div id="dashboard-icon" class="palm-dashboard-icon dashboard-icon-news"> </div> </div> <div class="palm-dashboard-text-container"> <div class="dashboard-title"> #{title} </div> <div id='dashboard-text' class="palm-dashboard-text">#{message}</div> </div> </div
These are all supported framework styles (most dashboard
named styles are loaded by the
framework), but we’ll add the dashboard-icon-news
in News.css to show the News icon, which is
located in the News application’s images directory:
.dashboard-icon-news { background: url(../images/dashboard-icon-news.png); }
This is a simple notification reminder, but dashboard summaries can be fully dynamic application views. You can provide ambient information that is accessed intermittently, like weather, stocks, baseball scores, or any information that a user wants to track and occasionally will tap to get more details. Dashboard summaries can be more sophisticated, like traffic monitors that not only provide tracking information, but also generate notifications to warn of traffic problems on routes of interest.
You can use dashboard summaries specifically to provide the display window for a background application, such as a location-based service or other applications that provide status and an occasional notification when an event occurs. This is a particular type of background application called a Dashboard Application and is covered more fully in the section Background Applications.
Like card stages, you can add a listener to the dashboard stage controller’s
document window for Mojo.Event.stageActivate
and Mojo.Event.stageDeactivate
events. When the
user taps the notification bar, the Dashboard view is opened and all
dashboard stages become maximized. When the user taps away or gestures
back, the Dashboard view is closed and all dashboard stages are
minimized.
Add event listeners to the dashboard scene assistant’s setup method:
this.stageDocument = this.controller.stageController.document; this.activateStageHandler = this.activateStage.bindAsEventListener(this); Mojo.Event.listen(this.stageDocument, Mojo.Event.stageActivate, this.activateStageHandler); this.deactivateStageHandler = this.deactivateStage.bindAsEventListener(this); Mojo.Event.listen(this.stageDocument, Mojo.Event.stageDeactivate, this.deactivateStageHandler);
Next, add handlers that will add a new feature to the dashboard.
When the stage is activated, display the most recent story in the feed
and start a three-second timer that, upon expiry, invokes the showStory()
method to update the dashboard
summary with a new story. The timer is reset so that the stories will
rotate as long as the dashboard is activated. On deactivate, clear the
timer:
DashboardAssistant.prototype.activateStage = function() { Mojo.Log.info("Dashboard stage Activation"); this.storyIndex = 0; this.showStory(); }; DashboardAssistant.prototype.deactivateStage = function() { Mojo.Log.info("Dashboard stage Deactivation"); this.stopShowStory(); }; // Tap to Dashboard should relaunch applications DashboardAssistant.prototype.launchMain = function() { Mojo.Log.info("Tap to Dashboard"); this.controller.serviceRequest('palm://com.palm.applicationManager', { method: "open", parameters: { id: "com.palm.app.news", params: {} } } ); this.controller.window.close(); }; // showStory - rotates stories shown in dashboard panel, every 3 seconds. // Only displays unread stories DashboardAssistant.prototype.showStory = function() { Mojo.Log.info("Dashboard Story Rotation", this.timer, this.storyIndex); this.interval = 3000; // If timer is null, just restart the timer and use the most recent story // or the last one displayed; if (!this.timer) { this.timer = this.controller.window.setInterval(this.showStory.bind(this), this.interval); } // Else, get next story in list and update the story in the dashboard display. else { // replace with test for unread story this.storyIndex = this.storyIndex+1; if(this.storyIndex >= this.list[this.index].stories.length) { this.storyIndex = 0; } this.message = this.list[this.index].stories[this.storyIndex].title; this.displayDashboard(this.title, this.message, this.count); } }; DashboardAssistant.prototype.stopShowStory = function() { if (this.timer) { this.controller.window.clearInterval(this.timer); this.timer = undefined; } };
You will also want to handle taps to the Dashboard panel by
calling your application’s main entry point and closing the dashboard
window, which closes the stage. In the code above, a listener is added
to the dashboardinfo
div for any tap
events. The handler uses the Application Manager to call the News entry
point.
In the next section, we’ll cover handling launch requests in the
application assistant. In those cases, you won’t use the Application
Manager service; instead, you will call the handleLaunch()
method of the application
controller.
3.129.42.244