Dashboards

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.

Note

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.

Back to the News: Adding a Dashboard Stage

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
A dashboard summary

Figure 10-3. A dashboard summary

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.

Handling Minimize, Maximize, and Tap Events

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.42.244