Example usage:
// addNewFeed - triggered by "Add..." item in feed list and invokes the AddDialog // Assistant defined above. // FeedListAssistant.prototype.addNewFeed = function() { this.controller.showDialog({ template: 'feedList/addFeed-dialog', assistant: new AddDialogAssistant(this) }); };
A custom dialog uses a template (HTML file) and an assistant (JavaScript file), similar to a scene. The HTML file defines what will be displayed in the custom dialog and the JavaScript file defines how the elements will behave.
Template file:
<div> <span id="add-feed-title" class="palm-dialog-title">Add News Feed Source</span> <div class="palm-group unlabeled"> <div class="palm-list"> <div class='palm-row first'> <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true"> <div class="title"> <div class="label">URL</div> <div id="newFeedURL" x-mojo-element="TextField" align="left"></div> </div> </div> </div> <div class='palm-row last'> <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true"> <div class="title"> <div class="label">Title</div> <div id="newFeedName" x-mojo-element="TextField" align="left"></div> </div> </div> </div> </div> </div> <div x-mojo-element="Button" id="okButton"></div> </div>
Here is the assistant for the dialog, which sets up the various widgets as well as the event handlers that will respond to user interaction with the widgets.
Assistant file:
// AddDialogAssistant - simple controller for adding new feeds to the list. // Invoked by the FeedListAssistant when the "Add..." list item is selected // on the feed list. // // The dialog displays two text fields (URL and Name) and an OK button. // Either the user enters a feed URL and a name, followed by OK or a // back swipe to close. If OK, the feed header is checked through an Ajax // request and if valid, the feed updated and dialog closed. If an error, // the posted in place of title and dialog remains open. // Swipe back cancels and returns back to the FeedListAssistant. // function AddDialogAssistant(sceneAssistant) { this.sceneAssistant = sceneAssistant; } AddDialogAssistant.prototype.setup = function(widget) { this.widget = widget; // Setup text field for the new feed's URL // this.sceneAssistant.controller.setupWidget("newFeedURL", this.urlAttributes = { property: "value", hintText: "RSS or ATOM feed", focus: true, limitResize: true, textReplacement: false, enterSubmits: false }, this.urlModel = {value : ""} ); // Setup text field for the new feed's name // this.sceneAssistant.controller.setupWidget("newFeedName", this.nameAttributes = { property: "value", hintText: "Optional", limitResize: true, textReplacement: false, enterSubmits: false }, this.nameModel = {value : "" }); // Setup button and event handler // this.sceneAssistant.controller.setupWidget("okButton", this.attributes = {}, this.model = { buttonLabel: "Add Feed", buttonClass: "addFeedButton", disabled: false } ); Mojo.Event.listen($('okButton'), Mojo.Event.tap, this.checkIt.bindAsEventListener(this)); }; // ------------------------------------------------------------------------ // Add Feed Functions // // checkIt - called when Add feed OK button is clicked // AddDialogAssistant.prototype.checkIt = function() { // Check for 'https://' on front or other legal prefix // assume any string of 1 to 5 alpha characters followed // by ':' is legal, otherwise prepend "https://" // var url = this.urlModel.value; if (/^[a-z]{1,5}:/.test(url) === false) { url = url.replace(/^\/{1,2}/,""); url = "https://"+url; } // Update the submitted URL text model this.urlModel.value = url; this.sceneAssistant.controller.modelChanged(this.urlModel); var request = new Ajax.Request(url, { method: 'get', evalJSON: 'false', onSuccess: this.checkOK.bind(this), onFailure: this.checkFailure.bind(this) }); }; // // checkOK - called when the Ajax request is successful. // AddDialogAssistant.prototype.checkOK = function(transport) { // DEBUG - log the result // var t = new Template("Status #{status} returned from newsfeed request."); var success = "Feed Request Success: "+t.evaluate(transport); Mojo.Log.info(success); // Work around when XML comes back in text response if (transport.responseXML === null && transport.responseText !== null) { Mojo.Log.info("••••••••","Request not in XML format - manually converting"); transport.responseXML = new DOMParser().parseFromString (transport.responseText, 'text/xml'); } var feedError = errorNone; // Push the entered feed onto feedlist and call processFeed to evaluate it. // This is mainly to record the user's TITLE entry before processing // feedList.push({title:this.nameModel.value, url:this.urlModel.value, type:"", acFreq:0, numUnRead:0, stories:[]}); feedError = ProcessFeed(transport); // If successful processFeed returns errorNone // if (feedError === errorNone) { this.sceneAssistant.feedWgtModel.items = feedList; this.sceneAssistant.controller.modelChanged(this.sceneAssistant.feedWgtModel); this.widget.mojo.close(); } else { feedList.pop(); if (feedError == errorUnsupportedFeedType) { Mojo.Log.info("Feed ", this.urlModel.value," isn't a recognized feed type (#", errorUnsupportedFeedType, ")"); $("add-feed-title").innerHTML ="Invalid Feed - not a supported feed type"; } } }; AddDialogAssistant.prototype.checkFailure = function(transport) { // Use the Prototype template object to generate a string from the return // var t = new Template($L("#{status}")); var m = t.evaluate(transport); // Log error and put message in status // Mojo.Log.info("Invalid feed (Status ", m, " returned)."); $("add-feed-title").innerHTML = "Invalid feed - http failure ("+m+")"; };
This example is from the book Palm webOS by Mitch Allen.