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.