--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/.project Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Symbian.org</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.nokia.wrt.widgetPreviewBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.nokia.wrt.WidgetProjectNature</nature>
+ <nature>com.aptana.ide.project.nature.web</nature>
+ </natures>
+</projectDescription>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/Bugzilla.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,273 @@
+
+
+var bugzillaTableStyle = "bugzilla";
+
+// Bugzilla access
+
+function BugzillaSearchPanel(parent) {
+ this.previousView = parent;
+ ListView.prototype.init.call(this, null, null);
+
+ // add the banner and 'title bar' - avoids the caption bug
+ var titleBar = new NavigationButton(null, "titlebar.png", "Bugzilla");
+ titleBar.setEnabled(false);
+ this.addControl(titleBar);
+
+ // search term control
+ this.searchTerm = new TextField('bugzillaSearchTerm', "Bugzilla search term:", "test");
+ this.addControl(this.searchTerm);
+
+ // add the search box
+ this.searchButton = new FormButton(null, "Search");
+ var self = this;
+ this.searchButton.addEventListener("ActionPerformed", function(){
+ self.bugzillaSearchClicked();
+ });
+ this.addControl(this.searchButton);
+}
+
+
+BugzillaSearchPanel.prototype = new ListView(null,null);
+
+
+BugzillaSearchPanel.prototype.bugzillaSearchClicked = function() {
+ // create the RssReader for bugzilla
+ var searchString = this.searchTerm.getText();
+ var title = "Bugzilla: " + searchString;
+ var url = symbianOrgBaseUrl + "/bugs/buglist.cgi?"
+ + "bug_status=NEW&bug_status=ASSIGNED&bug_status=UNCONFIRMED"
+ + "&field-1-0-0=bug_status&field0-0-0=product&field0-0-1=component&field0-0-2=short_desc"
+ + "&field0-0-3=status_whiteboard&field0-0-4=longdesc"
+ + "&query_format=advanced&remaction=&type-1-0-0=anyexact"
+ + "&type0-0-0=substring&type0-0-1=substring&type0-0-2=substring&type0-0-3=substring"
+ + "&type0-0-4=substring&value-1-0-0=NEW%2CASSIGNED%2CUNCONFIRMED"
+ + "&value0-0-0=" + searchString
+ + "&value0-0-1=" + searchString
+ + "&value0-0-2=" + searchString
+ + "&value0-0-3=" + searchString
+ + "&value0-0-4=" + searchString
+ + "&title=Bug List&ctype=atom";
+ var reader = new RssReader(title, url, new BugzillaFeedPresenter(null), this, parseBugzillaFeed);
+ reader.show();
+}
+
+
+function parseBugzillaFeed(broker, responseStatus, xmlDoc) {
+ if (responseStatus == 200 && xmlDoc != null) {
+ // node ref for iterating
+ var node;
+
+ // for compatibility with rss
+ var lastModified = new Date();
+
+ // init result items array
+ var items = [];
+
+ var itemElements = xmlDoc.getElementsByTagName("entry");
+
+ for (var i = 0; i < itemElements.length; i++) {
+ // iterate through child nodes of this item and gather
+ // all the data we need for a feed item
+ var title = null;
+ var date = null;
+ var description = null;
+ var url = null;
+ var author = null;
+ var bugid;
+ node = itemElements[i].firstChild;
+ while (node != null) {
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ if (node.nodeName == "title") {
+ // item title
+ title = getTextOfNode(node);
+ if ( title.length > 48) {
+ title = title.substring(0,45) + "...";
+ }
+ } else if (node.nodeName == "updated" ) {
+ // item publishing date
+ date = getTextOfNode(node);
+ } else if (node.nodeName == "summary" && !this.ignoreContent ) {
+ // item description
+ description = getTextOfNode(node);
+ } else if (node.nodeName == "link") {
+ // link URL
+ url = node.getAttribute("href");
+ // extract bug id
+ var ind = url.indexOf("?id=");
+ if ( ind != -1 ) {
+ bugid = url.substring(ind + 4);
+ url = symbianOrgBaseUrl + "/bugtracker/show_bug.cgi?ctype=xml&id="+bugid;
+ }
+ } else if (node.nodeName == "author" ) {
+ author = getTextOfNode(node);
+ }
+ }
+ node = node.nextSibling;
+ }
+ items.push({ title: title, date: date, description: description, url: url, author: author });
+ }
+
+ // update was completed successfully
+ return { status: "ok", lastModified: lastModified, items: items };
+ } else {
+ // update failed
+ return { status: "error" };
+ }
+}
+
+
+// Implementation of FeedPresenter that shows feed as a clickable
+// button and shows feed entry title as label
+function BugzillaFeedPresenter(rssreader) {
+ ButtonFeedPresenter.prototype.init.call(this, rssreader);
+}
+
+// BugzillaFeedPresenter is a subclass of ButtonFeedPresenter
+BugzillaFeedPresenter.prototype = new ButtonFeedPresenter(null);
+
+// Handle the button-press
+BugzillaFeedPresenter.prototype.feedClicked = function(event){
+ var clickedButton = event.source;
+ var id = clickedButton.id;
+ var url = this.items[id].url;
+ var presenter = new HtmlFeedPresenter(null);
+ presenter.expanded = true;
+ var reader = new RssReader(this.items[id].title, url,
+ presenter, uiManager.currentView, parseBugzillaBugFeed);
+ reader.show();
+}
+
+
+function parseBugzillaBugFeed(broker, responseStatus, xmlDoc) {
+ if (responseStatus == 200 && xmlDoc != null) {
+ // node ref for iterating
+ var node;
+
+ // for compatibility with rss
+ var lastModified = new Date();
+
+ // init result items array
+ var items = [];
+
+ var itemElements = xmlDoc.getElementsByTagName("bug");
+
+ for (var i = 0; i < itemElements.length; i++) {
+ // iterate through child nodes of this item and gather
+ // all the data we need for a feed item
+ var title = null;
+ var date = null;
+ var url = null;
+ var author = null;
+ var bugid = null;
+ var creationTime = "Not specified";
+ var product = "Not specified";
+ var component = "Not specified";
+ var classification = "Not specified";
+ var op_sys = "Not specified";
+ var bug_status = "Not specified";
+ var bug_file_loc = "Not specified";
+ var priority = "Not specified";
+ var severity = "Not specified";
+ var target_milestone = "Not specified";
+ var version = "Not specified";
+ var platform = "Not specified";
+ var assignedToName = "Not specified";
+ var solutionDetails = "Not specified";
+ var longdesc = "";
+ var shortDesc = "";
+ var bugid = "";
+
+ node = itemElements[i].firstChild;
+ while (node != null) {
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ if (node.nodeName == "bug_id") {
+ // item title
+ bugid = "Bug " + getTextOfNode(node);
+ } else if (node.nodeName == "updated" ) {
+ // item publishing date
+ date = getTextOfNode(node);
+ } else if (node.nodeName == "creation_ts" ) {
+ // item publishing date
+ creationTime = getTextOfNode(node);
+ } else if (node.nodeName == "short_desc" && !this.ignoreContent ) {
+ // item description
+ title = getTextOfNode(node);
+ } else if (node.nodeName == "reporter" ) {
+ author = getTextOfNode(node);
+ } else if (node.nodeName == "product" ) {
+ product = getTextOfNode(node);
+ } else if (node.nodeName == "component" ) {
+ component = getTextOfNode(node);
+ } else if (node.nodeName == "classification" ) {
+ classification = getTextOfNode(node);
+ } else if (node.nodeName == "version" ) {
+ version = getTextOfNode(node);
+ } else if (node.nodeName == "op_sys" ) {
+ op_sys = getTextOfNode(node);
+ } else if (node.nodeName == "bug_status" ) {
+ bug_status = getTextOfNode(node);
+ } else if (node.nodeName == "bug_file_loc" ) {
+ bug_file_loc = getTextOfNode(node);
+ } else if (node.nodeName == "priority" ) {
+ priority = getTextOfNode(node);
+ } else if (node.nodeName == "severity" ) {
+ severity = getTextOfNode(node);
+ } else if (node.nodeName == "target_milestone" ) {
+ target_milestone = getTextOfNode(node);
+ } else if (node.nodeName == "platform" ) {
+ platform = getTextOfNode(node);
+ } else if (node.nodeName == "cf_solutiondetails" ) {
+ solutionDetails = getTextOfNode(node);
+ } else if (node.nodeName == "long_desc" ) {
+ longdesc += "<br><table style="+bugzillaTableStyle+">";
+ var ld_nodes = node.childNodes;
+ for ( var tmp = 0 ; tmp < ld_nodes.length ; tmp++ ) {
+ longdesc += "<tr><td>"
+ + getTextOfNode(ld_nodes[tmp]) + "</td></tr>";
+ }
+ longdesc += "</table>";
+ } else if (node.nodeName == "assigned_to" ) {
+ assignedToName = getTextOfNode(node);
+ }
+ }
+ node = node.nextSibling;
+ }
+ // format the description
+ var description = "<table style="+bugzillaTableStyle+">";
+ description += "<tr><td>Reported:" + "</td><td>" + creationTime + "</td></tr>";
+ description += "<tr><td>Product:" + "</td><td>" + product + "</td></tr>";
+ description += "<tr><td>Component:" + "</td><td>" + component + "</td></tr>";
+ description += "<tr><td>Classification:" + "</td><td>" + classification + "</td></tr>";
+ description += "<tr><td>Operating system:" + "</td><td>" + op_sys + "</td></tr>";
+ description += "<tr><td>Status:" + "</td><td>" + bug_status + "</td></tr>";
+ description += "<tr><td>Priority:" + "</td><td>" + priority + "</td></tr>";
+ description += "<tr><td>Severity:" + "</td><td>" + severity + "</td></tr>";
+ description += "<tr><td>Version:" + "</td><td>" + version + "</td></tr>";
+ description += "<tr><td>Platform:" + "</td><td>" + platform + "</td></tr>";
+ description += "<tr><td>Reported by:" + "</td><td>" + author + "</td></tr>";
+ description += "<tr><td>Assigned to:" + "</td><td>" + assignedToName + "</td></tr>";
+ description += "<tr><td>Target milestone:" + "</td><td>" + target_milestone + "</td></tr>";
+ description += "<tr><td>File location:" + "</td><td>" + bug_file_loc + "</td></tr>";
+ description += "</table>";
+
+ description += "<table style="+bugzillaTableStyle+">";
+ description += "<tr><td>Description:" + "</td></tr>";
+ description += "<tr><td>" + longdesc + "</td></tr>";
+ description += "</table>";
+
+ description += "<table style="+bugzillaTableStyle+">";
+ description += "<tr><td>Solution details:" + "</td></tr>";
+ description += "<tr><td>" + solutionDetails + "</td></tr>";
+ description += "</table>";
+
+ items.push({ title: title, date: date, description: description, url: url, author: author });
+ }
+
+ // update was completed successfully
+ return { status: "ok", lastModified: lastModified, items: items };
+ } else {
+ // update failed
+ return { status: "error" };
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/FeedPresentation.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,155 @@
+// ////////////////////////////////////////////////////////////////////////////
+// (c)2009 Symbian Foundation
+// ////////////////////////////////////////////////////////////////////////////
+
+// Feed presentation classes
+
+// Abstract class used to create controls to represent feed entries.
+function FeedPresenter(rssreader){
+ if (rssreader) {
+ this.init(rssreader);
+ }
+}
+
+// FeedPresenter "Constructor"
+FeedPresenter.prototype.init = function(rssreader){
+ this.rssreader = rssreader;
+}
+
+// Create a control that represents this item and add it to
+// parent rss reader
+FeedPresenter.prototype.show = function(item){
+}
+
+// Create and add controls to be shown before items list.
+FeedPresenter.prototype.addPreambleItems = function(){
+}
+
+// No items returned, show "No messages"
+FeedPresenter.prototype.showNoItems = function(){
+ var label = new Label(null, null, "No messages");
+ this.rssreader.addControl(label);
+}
+
+// Implementation of FeedPresenter that shows feed in a
+// ContentPanel
+function HtmlFeedPresenter(rssreader) {
+ if (rssreader) {
+ this.init(rssreader);
+ }
+ this.expanded = false;
+}
+
+// HtmlFeedPresenter is a subclass of FeedPresenter
+HtmlFeedPresenter.prototype = new FeedPresenter(null);
+
+// HtmlFeedPresenter "constructor"
+HtmlFeedPresenter.prototype.init = function(rssreader) {
+ FeedPresenter.prototype.init.call(this, rssreader);
+}
+
+// Create a control that represents this item and add it to
+// parent rss reader
+HtmlFeedPresenter.prototype.show = function(item) {
+ // get a feed item control from the pool or create one and
+ // place it in the pool if there aren't enough feed item controls
+ var feedItemControl = new ContentPanel(null, null, null, true);
+
+ // initialize feed item control
+ feedItemControl.setCaption(item.title);
+ feedItemControl.setContent(this.getContentHTMLForFeedItem(item));
+ feedItemControl.setExpanded(this.expanded);
+
+ // add the feed item control to the main view
+ this.rssreader.feedItemControls.push(feedItemControl);
+ this.rssreader.addControl(feedItemControl);
+}
+
+// Returns the content HTML for a feed item.
+HtmlFeedPresenter.prototype.getContentHTMLForFeedItem = function (item){
+ var buf = "";
+
+ // item date
+ if (item.date != null) {
+ buf += "<div class=\"FeedItemDate\">" ;
+ if ( item.author != null ) {
+ buf += item.author + ", ";
+ }
+ buf += item.date + "</div>";
+ }
+
+ // item description
+ if (item.description != null) {
+ buf += "<div class=\"FeedItemDescription\">" + item.description + "</div>";
+ }
+
+ if (item.url != null) {
+ // blogs
+ buf += "<div class=\"FeedItemLink\">";
+// buf += "<a href=\"JavaScript:void(0)\" onclick=\"openURL('" + item.title + "', '" + item.url + "'); return false;\">";
+ buf += "<a href=\"JavaScript:void(0)\" onclick=\"openURL('" + item.url + "'); return false;\">";
+ buf += "Read more...";
+ buf += "</a>";
+ buf += "</div>";
+ }
+
+ return buf;
+}
+
+
+// Implementation of FeedPresenter that shows feed as a clickable
+// button that shows feed entry title as label
+function ButtonFeedPresenter(rssreader) {
+ if (rssreader) {
+ this.init(rssreader);
+ }
+ this.indexCounter = 0;
+ this.items = [];
+}
+
+// ButtonFeedPresenter is a subclass of FeedPresenter
+ButtonFeedPresenter.prototype = new FeedPresenter(null);
+
+// ButtonFeedPresenter "constructor"
+ButtonFeedPresenter.prototype.init = function(rssreader) {
+ FeedPresenter.prototype.init.call(this, rssreader);
+}
+
+// Create a control that represents this item and add it to
+// parent rss reader
+ButtonFeedPresenter.prototype.show = function(item) {
+ this.items[this.indexCounter] = item;
+ // get a feed item control from the pool or create one and
+ // place it in the pool if there aren't enough feed item controls
+ var feedItemControl = new NavigationButton(this.indexCounter, "right.gif", item.title);
+
+ // add button press handler
+ var self = this;
+ feedItemControl.addEventListener("ActionPerformed",
+ function(event) { self.feedClicked(event); } );
+
+ this.indexCounter++;
+
+ // add the feed item control to the main view
+ this.rssreader.feedItemControls.push(feedItemControl);
+ this.rssreader.addControl(feedItemControl);
+}
+
+// Handle the button-press
+ButtonFeedPresenter.prototype.feedClicked = function(event){
+ var clickedButton = event.source;
+ var id = clickedButton.id;
+ var url = this.items[id].url;
+
+ if (url.indexOf("/wiki/index.php")) {
+ // hack for printable wiki pages
+ var articleName = url.replace(wikiBaseUrl + "/", "");
+ url = wikiBaseUrl + "?title=" + articleName + "&action=render";
+ openURL(url);
+ }
+ else {
+ openURL(url);
+ }
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/FeedUpdateBroker.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,220 @@
+///////////////////////////////////////////////////////////////////////////////
+// The FeedUpdateBroker class implements a simple RSS fetcher and parser.
+// Adapted from WRTKit RssReader example
+
+// Constructor.
+function FeedUpdateBroker() {
+ this.httpReq = null;
+ this.feedAddress = null;
+ this.callback = null;
+ this.ignoreContent = false;
+ this.cancelled = false;
+ this.responseParser = this.handleRssResponse;
+ this.startFromItem = 0;
+ this.maxItems = 0;
+}
+
+// Fetches a feed from the specified URL and calls the callback when the feed
+// has been fetched and parsed, or if the process results in an error.
+FeedUpdateBroker.prototype.doFetchFeed = function(){
+ // create new XML HTTP request
+ this.httpReq = new Ajax();
+
+ // set callback
+ var self = this;
+ this.httpReq.onreadystatechange = function() { self.readyStateChanged(); };
+
+ var fullURL = this.feedAddress;
+ if (fullURL.indexOf("?") == -1) {
+ fullURL += "?";
+ } else {
+ fullURL += "&";
+ }
+ fullURL += "nocache=" + (new Date().getTime());
+
+ // initiate the request
+ this.httpReq.open("GET", fullURL, true);
+ this.httpReq.send(null);
+}
+
+// has been fetched and parsed, or if the process results in an error.
+FeedUpdateBroker.prototype.fetchFeed = function(feedURL, callback) {
+ // remember callback
+ this.callback = callback;
+ this.feedAddress = feedURL;
+ this.doFetchFeed();
+}
+
+// Callback for ready-state change events in the XML HTTP request.
+FeedUpdateBroker.prototype.readyStateChanged = function() {
+ // complete request?
+ if (this.httpReq.readyState == 4) {
+ // attempt to get response status
+ var responseStatus = null;
+ try {
+ responseStatus = this.httpReq.status;
+ } catch (noStatusException) {}
+
+ // are we being prompted for login?
+ var text = this.httpReq.responseText;
+ if ( isLoginPrompt (text) ) {
+ var self = this;
+ login(function(){self.doFetchFeed();});
+ return;
+ }
+
+ // handle the response and call the registered callback object
+ var response = this.httpReq.responseXML;
+ if (response == null) {
+ // if the content type is not set correctly, we get the response as text
+ var xmlparser = new DOMParser();
+ response = xmlparser.parseFromString(this.httpReq.responseText, "text/xml");
+ }
+ this.callback.feedUpdateCompleted(this.handleResponse(responseStatus, response));
+ }
+}
+
+// Handles a completed response.
+FeedUpdateBroker.prototype.handleResponse = function(responseStatus, xmlDoc){
+ if (this.responseParser == null) {
+ return this.handleRssResponse(responseStatus, xmlDoc);
+ }
+ else {
+ return this.responseParser.call(this, this, responseStatus, xmlDoc);
+ }
+}
+
+
+FeedUpdateBroker.prototype.handleRssResponse = function(broker, responseStatus, xmlDoc){
+ if ( this.cancelled ) {
+ return { status: "cancelled" };
+ }
+ if (responseStatus == 200 && xmlDoc != null) {
+ // node ref for iterating
+ var node;
+
+ // get last modified time - default to current time
+ var lastModified = new Date().getTime();
+ var channelElements = xmlDoc.getElementsByTagName("channel");
+ if (channelElements.length > 0) {
+ node = channelElements[0].firstChild;
+ while (node != null) {
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ if (node.nodeName == "pubDate" ||
+ node.nodeName == "lastBuildDate" ||
+ node.nodeName == "dc:date") {
+ lastModified = getTextOfNode(node);
+ break;
+ }
+ }
+ node = node.nextSibling;
+ }
+ }
+
+ // init feed items array
+ var items = [];
+
+ // we got the feed XML so now we'll parse it
+ var itemElements = xmlDoc.getElementsByTagName("item");
+
+ for (var i = this.startFromItem; i < itemElements.length; i++) {
+ if ( this.maxItems > 0 && this.maxItems < i ) {
+ break;
+ }
+ // iterate through child nodes of this item and gather
+ // all the data we need for a feed item
+ var title = null;
+ var date = null;
+ var description = null;
+ var url = null;
+ var author = null;
+ node = itemElements[i].firstChild;
+ while (node != null) {
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ if (node.nodeName == "title") {
+ // item title
+ title = getTextOfNode(node);
+ } else if (node.nodeName == "pubDate" || node.nodeName == "dc:date") {
+ // item publishing date
+ date = getTextOfNode(node);
+ } else if (node.nodeName == "description" && !this.ignoreContent ) {
+ // item description
+ description = getTextOfNode(node);
+ } else if (node.nodeName == "link") {
+ // link URL
+ url = getTextOfNode(node);
+ } else if (node.nodeName == "dc:creator" ) {
+ author = getTextOfNode(node);
+ }
+ }
+ node = node.nextSibling;
+ }
+
+ // create the item and add to the items array
+ items.push({ title: title, date: date, description: description, url: url, author: author });
+ }
+
+ // update was completed successfully
+ return { status: "ok", lastModified: lastModified, items: items };
+ } else {
+ // update failed
+ return { status: "error" };
+ }
+}
+
+// Returns the text of a node.
+function getTextOfNode(node) {
+ var buf = "";
+
+ // iterate through all child elements and collect all text to the buffer
+ var child = node.firstChild;
+ while (child != null) {
+ if (child.nodeType == Node.TEXT_NODE || child.nodeType == Node.CDATA_SECTION_NODE) {
+ // append text to buffer
+ if (buf != "") {
+ buf += " ";
+ }
+ buf += child.nodeValue;
+ }
+ child = child.nextSibling;
+ }
+
+ // strip all tags from the buffer
+ var strippedBuf = "";
+ var textStartPos = -1;
+ var tagBalance = 0;
+
+ // iterate through the text and append all text to the stripped buffer
+ // that is at a tag balance of 0
+ for (pos = 0; pos < buf.length; pos++) {
+ var c = buf.charAt(pos);
+ if (c == '<') {
+ // entering a tag
+ if (tagBalance == 0 && textStartPos != -1) {
+ // everything up to here was valid text
+ strippedBuf += buf.substring(textStartPos, pos);
+ textStartPos = -1;
+ }
+ tagBalance++;
+ } else if (c == '>') {
+ // leaving a tag
+ tagBalance--;
+ textStartPos = -1;
+ } else if (tagBalance == 0 && textStartPos == -1) {
+ // first char of text
+ textStartPos = pos;
+ }
+ }
+
+ // add remaining text - if any
+ if (tagBalance == 0 && textStartPos != -1) {
+ strippedBuf += buf.substring(textStartPos, pos);
+ }
+
+ return strippedBuf;
+}
+
+FeedUpdateBroker.prototype.cancel = function() {
+ this.cancelled = true;
+ this.httpReq.abort();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/ForumPostForm.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,328 @@
+// ////////////////////////////////////////////////////////////////////////////
+// (c)2009 Symbian Foundation
+// ////////////////////////////////////////////////////////////////////////////
+
+
+function ForumPostForm(aParentView, forumid) {
+ ListView.prototype.init.call(this, null, null);
+ this.previousView = aParentView;
+ this.forumid = forumid;
+
+ // add the banner / 'title bar' - avoids the caption bug
+ var titleBar = new NavigationButton(null, "titlebar.png", "New thread in " + aParentView.feedName);
+ titleBar.setEnabled(false);
+ this.addControl(titleBar);
+
+ // add topic name textfield
+ this.topicNameTf = new TextField('threadPostTopic', "Topic title", "");
+ this.addControl(this.topicNameTf);
+
+ // add content textarea
+ this.contentTa = new TextArea('threadPostContent', "Message", "", 6);
+ this.addControl(this.contentTa);
+
+ var self = this;
+
+ // post button
+ this.postButton = new FormButton(null, "Submit");
+ this.postButton.addEventListener("ActionPerformed", function(){
+ login( function(){
+ submitNewTopic(
+ self.topicNameTf.getText(), // title
+ self.contentTa.getText(), // message
+ self.forumid, // forumid
+ function() { self.goBack();uiManager.currentView.update(true);}
+ );
+ });
+ });
+ this.addControl(this.postButton);
+
+ // cancel settings button
+ this.cancelButton = new FormButton(null, "Cancel");
+ this.cancelButton.addEventListener("ActionPerformed", function(){self.goBack();});
+ this.addControl(this.cancelButton);
+
+}
+
+ForumPostForm.prototype = new ListView(null, null);
+
+
+function ForumReplyForm(aParentView, threadid, postid, parentTitle) {
+ ListView.prototype.init.call(this, null, null);
+ this.previousView = aParentView;
+ this.threadid = threadid;
+ this.postid = postid;
+ this.parentTitle = parentTitle;
+
+ // add the banner / 'title bar' - avoids the caption bug
+ var titleBar = new NavigationButton(null, "titlebar.png", "Reply to " + parentTitle);
+ titleBar.setEnabled(false);
+ this.addControl(titleBar);
+
+ // add topic name textfield
+ this.topicNameTf = new TextField('threadPostTopic', "Title", "");
+ this.addControl(this.topicNameTf);
+
+ // add content textarea
+ this.contentTa = new TextArea('threadPostContent', "Message", "", 6);
+ this.addControl(this.contentTa);
+
+ var self = this;
+
+ // post button
+ this.postButton = new FormButton(null, "Submit");
+ this.postButton.addEventListener("ActionPerformed", function(){
+ login(
+ function(){
+ submitNewReply(self.topicNameTf.getText(), // title
+ self.contentTa.getText(), // message
+ self.threadid, // threadid
+ self.postid, // threadid
+ function(){
+ self.goBack();
+ uiManager.currentView.update(true);
+ });
+ });
+ });
+ this.addControl(this.postButton);
+
+ // cancel settings button
+ this.cancelButton = new FormButton(null, "Cancel");
+ this.cancelButton.addEventListener("ActionPerformed", function(){self.goBack();});
+ this.addControl(this.cancelButton);
+
+}
+
+ForumReplyForm.prototype = new ListView(null, null);
+
+
+// Submitting a new to vBulletin is somewhat complex. There appears to be
+// no XML based interface so we have to go through the usual web posting
+// procedure. So, first we must be logged in. Then, we must request forums
+// home page to get bbsessionhash cookie. Next, we request the form,
+// to collect required security information (securitytoken etc) from the form.
+// If all goes well, we can now post a message.
+
+var submitUrlContent = null;
+var submitUrlHttpReq = null;
+var submitCallback = null;
+var submitTitle = null;
+var submitContent = null;
+var submitForumId = null;
+var submitThreadId = null;
+var submitPostId = null;
+var submitCallback = null;
+var reply = false;
+
+// Initiates the submission process by requesting the form
+function submitNewTopic(title, content, forumid, callback){
+ uiManager.showNotification(-1, "wait", "Submitting...", -1);
+
+ // Dealing with vBulletin nastiness...
+
+ // ensure we have all the cookies we need
+ var vbCookieGet = new Ajax();
+ var vburl = symbianOrgBaseUrl + "/forum/";
+ vbCookieGet.open('GET', vburl, false);
+ vbCookieGet.send(null);
+
+ // Now we have to harvest some info from the post form.
+ submitUrlHttpReq = new Ajax();
+ var self = this;
+ submitTitle = title;
+ submitContent = content;
+ submitForumId = forumid;
+ submitThreadId = null;
+ submitPostId = null;
+ submitCallback = callback;
+ submitUrlHttpReq.onreadystatechange = submitFormReady;
+ reply = false;
+
+ var url = symbianOrgBaseUrl + "/forum/newthread.php?do=newthread&f=" + forumid;
+ submitUrlHttpReq.open('GET', url, true);
+ submitUrlHttpReq.send(null);
+}
+
+// Initiates the submission process by requesting the form
+function submitNewReply(title, content, threadid, postid, callback){
+ uiManager.showNotification(-1, "wait", "Submitting...", -1);
+
+ // Dealing with vBulletin nastiness...
+
+ // ensure we have all the cookies we need
+ var vbCookieGet = new Ajax();
+ var vburl = symbianOrgBaseUrl + "/forum/";
+ vbCookieGet.open('GET', vburl, false);
+ vbCookieGet.send(null);
+
+ // Now we have to harvest some info from the post form.
+ submitUrlHttpReq = new Ajax();
+ var self = this;
+ submitTitle = title;
+ submitContent = content;
+ submitForumId = null;
+ submitThreadId = threadid;
+ submitPostId = postid;
+ submitCallback = callback;
+ submitUrlHttpReq.onreadystatechange = submitFormReady;
+ reply = true;
+
+ var url = symbianOrgBaseUrl + "/forum/newreply.php?do=newreply&noquote=1&p=" + postid;
+ submitUrlHttpReq.open('GET', url, true);
+ submitUrlHttpReq.send(null);
+}
+
+
+var forumPostHarvestString_loggedinuser = "name=\"loggedinuser\" value=\"";
+var forumPostHarvestString_poststarttime = "name=\"poststarttime\" value=\"";
+var forumPostHarvestString_posthash = "name=\"posthash\" value=\"";
+var forumPostHarvestString_securitytoken = "name=\"securitytoken\" value=\"";
+
+// Form has been received, extract important info
+function submitFormReady(){
+ uiManager.showNotification(-1, "wait", "Submitting...", -1);
+ if (submitUrlHttpReq.readyState == 4) {
+ // attempt to get response status
+ var responseStatus = null;
+ try {
+ responseStatus = submitUrlHttpReq.status;
+ } catch (noStatusException) {}
+
+
+ var content = submitUrlHttpReq.responseText;
+ checkForSecurityToken("submitFormReady", content);
+
+ // this is what we need to hardvest
+ var forumPostSecurityToken, forumPostHash, forumPostStartTime, forumPostLoggedInUser;
+
+ if ( content.indexOf(forumPostHarvestString_loggedinuser) == -1 ) {
+ uiManager.showNotification(5000, "warning", "Submit failed.");
+ } else {
+ forumPostLoggedInUser = extractFormField(content, forumPostHarvestString_loggedinuser);
+ forumPostStartTime = extractFormField(content, forumPostHarvestString_poststarttime);
+ forumPostHash = extractFormField(content, forumPostHarvestString_posthash);
+ forumPostSecurityToken = extractFormField(content, forumPostHarvestString_securitytoken);
+
+ if (forumPostSecurityToken == null || forumPostSecurityToken.length < 5) {
+ // workaround for a vBulletin bug, restart the process...
+ login( function(){
+ if (reply) {
+ submitNewReply(submitTitle, // title
+ submitContent, // message
+ submitThreadId, // threadid
+ submitPostId, // threadid
+ submitCallback);
+ }
+ else {
+ submitNewTopic(submitTitle, // title
+ submitContent, // message
+ submitForumId, // forumid
+ submitCallback);
+ }
+ });
+ } else {
+ doSubmitPost(submitTitle, submitContent, submitForumId, submitCallback, forumPostSecurityToken, forumPostHash, forumPostStartTime, forumPostLoggedInUser);
+ }
+ }
+ }
+}
+
+// Send a POST request with our post information
+function doSubmitPost(title, message, forumid, callback,
+ forumPostSecurityToken, forumPostHash, forumPostStartTime, forumPostLoggedInUser){
+ uiManager.showNotification(-1, "wait", "Submitting...", -1);
+ var url = null;
+ var parameters = null;
+
+ if (reply) {
+ // posting a reply to an article
+ url = symbianOrgNewReplyUrl + "do=postreply&t=" + submitThreadId;
+ parameters = "title=" + title + "&message=" + message +
+ "&wysiwyg=0&iconid=0&s=&securitytoken=" + forumPostSecurityToken +
+ "&do=postreply" +
+ "&t=" + submitThreadId + "&p=" + submitPostId +
+ "&specifiedpost=0" +
+ "&posthash" + forumPostHash +
+ "&poststarttime=" + forumPostStartTime +
+ "&loggedinuser=" + forumPostLoggedInUser +
+ "&multiquoteempty=&sbutton=Submit+Reply&parseurl=1&emailupdate=9999&rating=0";
+ } else {
+ // posting a new thread
+ url = symbianOrgNewThreadUrl + "do=postthread&f=" + forumid;
+ parameters = "do=postthread&f=" + forumid + "&subject=" + title + "&message=" + message +
+ "&wysiwyg=0&taglist=&iconid=0&s=&securitytoken=" + forumPostSecurityToken +
+ "&posthash" + forumPostHash +
+ "&poststarttime=" + forumPostStartTime +
+ "&loggedinuser=" + forumPostLoggedInUser +
+ "&sbutton=Submit+New+Thread&parseurl=1&emailupdate=9999&polloptions=4";
+ }
+
+ submitUrlHttpReq = new Ajax();
+ submitUrlHttpReq.onreadystatechange = submitComplete;
+ // initiate the request
+ submitUrlHttpReq.open('POST', url, true);
+ submitUrlHttpReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ submitUrlHttpReq.setRequestHeader("Content-length", parameters.length);
+ submitUrlHttpReq.setRequestHeader("Connection", "close");
+ submitUrlHttpReq.send(parameters);
+}
+
+// Response to our POST has been received, analyse the result
+function submitComplete(){
+ if (submitUrlHttpReq.readyState == 4) {
+ // attempt to get response status
+ var responseStatus = null;
+ try {
+ responseStatus = submitUrlHttpReq.status;
+ }
+ catch (noStatusException) {
+ }
+ var content = submitUrlHttpReq.responseText;
+ if ( content.indexOf(submitTitle) == -1 ) {
+ uiManager.showNotification(3000, "warning", "Posting failed.");
+ } else {
+ uiManager.showNotification(3000, "warning", "Please wait...");
+ if ( submitCallback != null ) {
+ submitCallback.call();
+ }
+ }
+ }
+}
+
+// Test weather page HTML contains a login form. This is useful in
+// being able to tell weather a login has been successfull, or if
+// we received login prompt instead of XML at any point.
+function isLoginPrompt (text) {
+ return text.indexOf("form name=\"frmLogin\"") != -1;
+}
+
+// Stores the current view, then shows the settings dialog
+// so that once settings dialog is closed, we go back to current screen
+function promptForPassword() {
+ if (uiManager.currentView == settings) {
+ settings.previousView = home;
+ }
+ else {
+ settings.previousView = uiManager.currentView;
+ }
+ uiManager.hideNotification();
+ settings.show();
+}
+
+function extractFormField(content, harvestString){
+ var startind = content.indexOf(harvestString);
+ if ( startind == -1 ) {
+ return null;
+ }
+ startind += harvestString.length;
+ var endind = content.indexOf("\"", startind);
+ return content.substring(startind, endind);
+}
+
+function checkForSecurityToken(where, content) {
+// var stpos = content.indexOf("securitytoken");
+// if ( stpos == -1 ) {
+// var test = content.substring(stpos , stpos + 100);
+// alert("securityToken not found in " + where + " : "+ test);
+// }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/Forums.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,443 @@
+// ////////////////////////////////////////////////////////////////////////////
+// (c)2009 Symbian Foundation
+// ////////////////////////////////////////////////////////////////////////////
+
+// Forums
+
+// Forums have the following structure:
+//
+// Forum group list
+// Forum list
+// Thread list
+// Message list
+
+// All four views are based on customised RssReader. We customise two aspects:
+// - Parsing XML - data is not RSS
+// - Handling item selection (e.g. creating a new view for a newly selected forum)
+
+// /////////////////////////////////////////////////////////////////////////////
+// Forum groups
+
+// response parser for forum groups
+function forumGroupsResponseParser(broker, responseStatus, xmlDoc) {
+ if (responseStatus == 200 && xmlDoc != null) {
+ // node ref for iterating
+ var node;
+
+ // for compatibility with rss
+ var lastModified = new Date();
+
+ // init result items array
+ var items = [];
+
+ var elements = xmlDoc.getElementsByTagName("group");
+ for (var i = 0; i < elements.length; i++) {
+ var groupid = elements[i].getAttribute("id");
+ var grouptitle = elements[i].getAttribute("title");
+ items.push({ id: groupid, title: grouptitle});
+ }
+
+ // update was completed successfully
+ return { status: "ok", lastModified: lastModified, items: items };
+ } else {
+ // update failed
+ return { status: "error" };
+ }
+}
+
+// FeedPresenter implementation for forum groups
+function ForumGroupsFeedPresenter(rssreader){
+ if (rssreader) {
+ this.init(rssreader);
+ }
+}
+
+// ForumGroupsFeedPresenter is a subclass of ButtonFeedPresenter
+ForumGroupsFeedPresenter.prototype = new ButtonFeedPresenter(null);
+
+// ForumGroupsFeedPresenter "Constructor"
+ForumGroupsFeedPresenter.prototype.init = function(rssreader) {
+ ButtonFeedPresenter.prototype.init.call(this, rssreader);
+}
+
+// Handle the click on a specific item
+ForumGroupsFeedPresenter.prototype.feedClicked = function(event){
+ var buttonid = event.source.id;
+
+ if (buttonid == "latestPosts") {
+ // show latest posts
+ var url = forumFeedURL;
+ var latestPostsView = new RssReader("Latest posts", url, new LatestPostsFeedPresenter(null), this.rssreader, null);
+ latestPostsView.show();
+ }
+ else {
+ // show forum group
+ var groupid = this.items[buttonid].id;
+ var grouptitle = this.items[buttonid].title;
+
+ var url = forumsListUrl + groupid;
+ var forumListView = new RssReader(grouptitle, url, new ForumsListFeedPresenter(null), this.rssreader, forumListResponseParser);
+ forumListView.show();
+ }
+}
+
+// Create and add controls to be shown before items list.
+ForumGroupsFeedPresenter.prototype.addPreambleItems = function(){
+ var feedItemControl = new NavigationButton("latestPosts", "blueright.gif", "Latest posts");
+ var self = this;
+ feedItemControl.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); });
+ this.rssreader.addControl(feedItemControl);
+}
+
+
+// ///////////////////////////////////////////////////////////////////////////
+// List of forums in a group
+
+// response parser for forum list - in a group
+function forumListResponseParser(broker, responseStatus, xmlDoc) {
+ if (responseStatus == 200 && xmlDoc != null) {
+ // node ref for iterating
+ var node;
+
+ // for compatibility with rss
+ var lastModified = new Date();
+
+ // init result items array
+ var items = [];
+
+ // extract items for all group elements
+ var elements = xmlDoc.getElementsByTagName("group");
+ for (var i = 0; i < elements.length; i++) {
+ var forumid = elements[i].getAttribute("id");
+ var forumtitle = elements[i].getAttribute("title");
+ items.push({ id: forumid, title: forumtitle});
+ }
+
+ // update was completed successfully
+ return { status: "ok", lastModified: lastModified, items: items };
+ } else {
+ // update failed
+ return { status: "error" };
+ }
+}
+
+// FeedPresenter implementation for forum groups
+function ForumsListFeedPresenter(rssreader){
+ if (rssreader) {
+ this.init(rssreader);
+ }
+}
+
+// ForumsListFeedPresenter is a subclass of ButtonFeedPresenter
+ForumsListFeedPresenter.prototype = new ButtonFeedPresenter(null);
+
+// ForumsListFeedPresenter constructor
+ForumsListFeedPresenter.prototype.init = function(rssreader) {
+ ButtonFeedPresenter.prototype.init.call(this, rssreader);
+}
+
+
+// forum has been selected, create a reader showing threads in the forum
+ForumsListFeedPresenter.prototype.feedClicked = function(event){
+ var buttonid = event.source.id;
+ if (buttonid == "latestPosts") {
+ // show latest posts
+ var url = forumFeedURL + "&forumids=";
+ // append requested forum ids
+ for( var i = 0; i < this.items.length; i++) {
+ url += this.items[i].id + ",";
+ }
+
+ var latestPostsView = new RssReader(
+ "Latest posts in " + this.rssreader.feedName,
+ url,
+ new LatestPostsFeedPresenter(null),
+ this.rssreader,
+ null);
+ latestPostsView.show();
+ }
+ else {
+ var forumid = this.items[buttonid].id;
+ var forumtitle = this.items[buttonid].title;
+
+ var url = forumFeedURL + forumsForumSpecQuery + forumid;
+ var forumListView = new RssReader(forumtitle, url, new ThreadListFeedPresenter(null), this.rssreader, null);
+ forumListView.show();
+ }
+}
+
+// Create and add controls to be shown before items list.
+ForumsListFeedPresenter.prototype.addPreambleItems = function(){
+ var feedItemControl = new NavigationButton("latestPosts", "blueright.gif", "Latest posts in " + this.rssreader.feedName);
+ var self = this;
+ feedItemControl.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); });
+ this.rssreader.addControl(feedItemControl);
+}
+
+
+
+// ///////////////////////////////////////////////////////////////////////////
+// List of threads in a forum
+
+// response parser for thread list is the usual rss parser
+
+// FeedPresenter implementation for forum groups
+function ThreadListFeedPresenter(rssreader){
+ if (rssreader) {
+ this.init(rssreader);
+ }
+}
+
+// ThreadListFeedPresenter is a subclass of ButtonFeedPresenter
+ThreadListFeedPresenter.prototype = new ButtonFeedPresenter(null);
+
+// ThreadListFeedPresenter constructor
+ThreadListFeedPresenter.prototype.init = function(rssreader) {
+ ButtonFeedPresenter.prototype.init.call(this, rssreader);
+}
+
+
+// Handle the click on a specific item
+ThreadListFeedPresenter.prototype.feedClicked = function(event){
+ var buttonid = event.source.id;
+
+ if (buttonid == "newThread") {
+ // extract forum id from rssreader.feedURL
+ var ind = this.rssreader.feedURL.indexOf(forumsForumSpecQuery);
+ var forumid = this.rssreader.feedURL.substring( ind + forumsForumSpecQuery.length);
+ var postForm = new ForumPostForm(this.rssreader, forumid);
+ postForm.show();
+ }
+ else {
+ var weburl = this.items[buttonid].url;
+
+ // extract thread id from url. looking for t=xxx
+ var ind1 = weburl.indexOf("?t=");
+ if (ind1 == -1) {
+ ind1 = weburl.indexOf("&t=");
+ }
+ if (ind1 != -1) {
+ var threadid = "";
+ var ind2 = weburl.indexOf("&", ind1);
+ if (ind2 == -1) {
+ threadid = weburl.substring(ind1 + 3); // ?t=
+ }
+ else {
+ threadid = weburl.substring(ind1 + 3, ind2); // ?t=
+ }
+ var url = forumThreadUrl + threadid;
+ var title = this.items[buttonid].title;
+ if (title.length > 30) {
+ title = title.substring(0, 30) + "...";
+ }
+ var threadView = new RssReader(title, url, new ThreadFeedPresenter(null), this.rssreader, threadResponseParser);
+ threadView.show();
+ }
+ }
+}
+
+// Create and add controls to be shown before items list.
+ThreadListFeedPresenter.prototype.addPreambleItems = function(){
+ var feedItemControl = new NavigationButton("newThread", "blueright.gif", "Post a new thread");
+ var self = this;
+ feedItemControl.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); });
+ this.rssreader.addControl(feedItemControl);
+}
+
+// ///////////////////////////////////////////////////////////////////////////
+// List of messages in a thread
+
+// response parser for thread list
+function threadResponseParser(broker, responseStatus, xmlDoc) {
+ if (responseStatus == 200 && xmlDoc != null) {
+ // node ref for iterating
+ var node;
+
+ // for compatibility with rss
+ var lastModified = new Date();
+
+ // init result items array
+ var items = [];
+
+ // iterate over message elements
+ var elements = xmlDoc.getElementsByTagName("message");
+ for (var i = 0; i < elements.length; i++) {
+ var postid;
+ var threadid;
+ var username;
+ var title;
+ var dateline;
+ var pagetext;
+ var isdeleted;
+
+ // extract info about the post
+ node = elements[i].firstChild;
+ while (node != null) {
+ if ( node.nodeName == "postid" ) postid=getTextOfNode(node);
+ else if ( node.nodeName == "threadid" ) threadid=getTextOfNode(node);
+ else if ( node.nodeName == "username" ) username=getTextOfNode(node);
+ else if ( node.nodeName == "title" ) title=getTextOfNode(node);
+ else if ( node.nodeName == "dateline" ) dateline=getTextOfNode(node);
+ else if ( node.nodeName == "pagetext" ) pagetext=getTextOfNode(node);
+ else if ( node.nodeName == "isdeleted" ) isdeleted=getTextOfNode(node);
+ node = node.nextSibling;
+ }
+ if ( isdeleted == 1 ) continue;
+
+ items.push({
+ postid: postid,
+ threadid: threadid,
+ username: username,
+ title: title,
+ dateline: dateline,
+ pagetext: pagetext
+ });
+ }
+
+ // update was completed successfully
+ return { status: "ok", lastModified: lastModified, items: items };
+ } else {
+ // update failed
+ return { status: "error" };
+ }
+}
+
+// FeedPresenter implementation for forum groups
+function ThreadFeedPresenter(rssreader){
+ if (rssreader) {
+ this.init(rssreader);
+ }
+}
+
+// ThreadFeedPresenter is a subclass of HtmlFeedPresenter
+ThreadFeedPresenter.prototype = new HtmlFeedPresenter(null);
+
+// ThreadFeedPresenter constructor
+ThreadFeedPresenter.prototype.init = function(rssreader) {
+ HtmlFeedPresenter.prototype.init.call(this, rssreader);
+}
+
+
+// Handle the click on a specific item
+ThreadFeedPresenter.prototype.feedClicked = function(event){
+ // do nothing
+}
+
+// Create a control that represents this item and add it to
+// parent rss reader
+ThreadFeedPresenter.prototype.show = function(item) {
+ // get a feed item control from the pool or create one and
+ // place it in the pool if there aren't enough feed item controls
+ var feedItemControl = new ContentPanel(null, null, null, true);
+
+ // initialize feed item control
+ var title = item.title;
+ if ( title.length == 0 ) {
+ title = "Re:";
+ item.title = title;
+ }
+ feedItemControl.setCaption(bbcode2html(title));
+ feedItemControl.setContent(this.getContentHTMLForFeedItem(item));
+ feedItemControl.setExpanded(true);
+
+ // add the feed item control to the main view
+ this.rssreader.feedItemControls.push(feedItemControl);
+ this.rssreader.addControl(feedItemControl);
+}
+
+// Generate HTML content from the feed item
+ThreadFeedPresenter.prototype.getContentHTMLForFeedItem = function (item){
+ var buf = "";
+
+ // item date
+ if (item.dateline != null) {
+ var date = new Date();
+ date.setTime(item.dateline*1000);
+ buf += "<div class=\"FeedItemDate\">" ;
+ if ( item.username != null ) {
+ buf += item.username + ", ";
+ }
+ buf += date + "</div>";
+ }
+
+ // item description
+ if (item.pagetext != null) {
+ var text = bbcode2html(item.pagetext);
+ text = text.replace(/\r\n/g, "<br>");
+ buf += "<div class=\"FeedItemDescription\">" + text + "</div>";
+ buf += "<div class=\"FeedItemLink\">";
+ buf += "<a href=\"JavaScript:void(0)\" onclick=\"showReplyForm("
+ + item.threadid+ "," + item.postid + ", '" + item.title
+ + "'); return false;\">";
+ buf += "<strong>Reply to this post<strong></a>"
+ buf += "</div>";
+ }
+
+ return buf;
+}
+
+// Show the reply-to-post form
+function showReplyForm(threadid, postid, title) {
+ var replyForm = new ForumReplyForm(uiManager.currentView, threadid, postid, title);
+ replyForm.show();
+}
+
+
+// ///////////////////////////////////////////////////////////////////////////
+// Latest posts - same as ThreadListFeedPresenter, only has no preamble items
+// because it doesn't show one thread (so we can't post to latest items)...
+
+// FeedPresenter implementation for latest posts
+function LatestPostsFeedPresenter(rssreader){
+ if (rssreader) {
+ this.init(rssreader);
+ }
+}
+
+LatestPostsFeedPresenter.prototype = new ThreadListFeedPresenter(null);
+
+// ForumGroupsFeedPresenter "Constructor"
+LatestPostsFeedPresenter.prototype.init = function(rssreader) {
+ ButtonFeedPresenter.prototype.init.call(this, rssreader);
+}
+
+// LatestPostsFeedPresenter has no preamble items
+LatestPostsFeedPresenter.prototype.addPreambleItems = function(){
+}
+
+
+// ///////////////////////////////////////////////////////////////////////////
+// Utilities
+
+
+// feeds contain bbcodes - this function should turn the bbcode markup
+// to HTML
+function bbcode2html(s) {
+ return sanitize(s);
+}
+
+// Forum posts can be be quite messy and include bbcodes, smilies etc.
+// This function does the minimum by stripping bbcodes and such
+function sanitize(text) {
+ var prevind = 0;
+ var ind = text.indexOf("[");
+ if ( ind == -1 ) return text;
+ var buf = "";
+ while ( ind != -1 ) {
+ buf += text.substring(prevind, ind);
+ var ind2 = text.indexOf("]", ind);
+ if ( ind2 != -1 ) {
+ prevind = ind2+1;
+ } else {
+ break;
+ }
+ ind = text.indexOf("[", prevind);
+ }
+ if ( prevind > 0 && prevind < text.length) {
+ buf += text.substring(prevind);
+ }
+ return buf;
+}
+
+
+
Binary file Symbian.org/Icon.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/Info.plist Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Nokia//DTD PLIST 1.0//EN" "http://www.nokia.com/NOKIA_COM_1/DTDs/plist-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>DisplayName</key>
+ <string>Symbian.org</string>
+ <key>Identifier</key>
+ <string>org.symbian.developer.widget</string>
+ <key>Version</key>
+ <string>1.0</string>
+ <key>MainHTML</key>
+ <string>index.html</string>
+ <key>AllowNetworkAccess</key>
+ <true/>
+ </dict>
+</plist>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/Login.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,76 @@
+// ////////////////////////////////////////////////////////////////////////////
+// (c)2009 Symbian Foundation
+// ////////////////////////////////////////////////////////////////////////////
+
+
+// Login to the developer site
+
+var loginUrlContent = null;
+var loginUrlHttpReq = null;
+var loginCallback = null;
+
+function login(callback){
+ if ( forumUsername == null || forumPassword == null ) {
+ loginInitiated = true;
+ loginInitiatedCallback = callback;
+ promptForPassword();
+ return;
+ }
+ loginCallback = callback;
+ loginInitiated = false;
+ loginInitiatedCallback = null;
+ uiManager.showNotification(-1, "wait", "Please wait...", -1);
+
+ var parameters = symbianOrgLoginUsernameField + "=" + forumUsername
+ + "&" + symbianOrgLoginPasswordField + "=" + forumPassword
+ + "&submit=Login&image_submit.x=0&image_submit.y=0&image_submit=submit"
+ + "&referrer="+symbianOrgBaseUrl;
+ loginUrlHttpReq = new Ajax();
+ loginUrlHttpReq.onreadystatechange = loginComplete;
+
+ // initiate the request
+ loginUrlHttpReq.open('POST', symbianOrgLoginUrl +"?referer="+symbianOrgBaseUrl, true);
+ loginUrlHttpReq.setRequestHeader("Referer", symbianOrgBaseUrl);
+ loginUrlHttpReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ loginUrlHttpReq.setRequestHeader("Content-length", parameters.length);
+ loginUrlHttpReq.setRequestHeader("Connection", "close");
+ loginUrlHttpReq.send(parameters);
+}
+
+function loginComplete(){
+ if ( loginUrlHttpReq == null ) {
+ return;
+ }
+ // complete request?
+ var readyState = loginUrlHttpReq.readyState;
+ // attempt to get response status
+ var responseStatus = null;
+ try {
+ responseStatus = loginUrlHttpReq.status;
+ } catch (noStatusException) {}
+ if (readyState == 4) {
+
+ if (responseStatus < 300) {
+
+ var content = loginUrlHttpReq.responseText;
+ if (content.indexOf("LoginWelcome") == -1) {
+ uiManager.showNotification(3000, "warning", "Login failed.");
+ promptForPassword();
+ }
+ else {
+ uiManager.hideNotification();
+ if (loginCallback != null) {
+ loginCallback.call();
+ }
+ checkForSecurityToken("loginComplete", content);
+ }
+ } else if (responseStatus < 400) {
+ // do nothing, this must be a redirect
+ } else {
+ uiManager.hideNotification();
+ uiManager.showNotification(3000, "warning", "Login failed.");
+ promptForPassword();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/Main.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,348 @@
+// ////////////////////////////////////////////////////////////////////////////
+// (c)2009 Symbian Foundation
+// ////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// A widget for accessing developer.symbian.org forums
+
+
+// Reference to the WRTKit user interface manager and main view.
+var uiManager;
+
+// Global settings / URLs and such
+
+// Symbian.org web site base URL
+//var symbianOrgBaseUrl = "http://staging.foundationhost.org";
+//var symbianOrgBaseUrlSsl = "https://staging.foundationhost.org";
+var symbianOrgBaseUrl = "http://developer.symbian.org";
+var symbianOrgBaseUrlSsl = "https://developer.symbian.org";
+var registrationURL = symbianOrgBaseUrl + "/main/user_profile/register.php";
+var blogFeedName = "Symbian Blog";
+var blogFeedUrl = "http://blog.symbian.org/feed/";
+
+// FORUM vars and settings
+var symbianOrgNewThreadUrl = symbianOrgBaseUrl+"/forum/newthread.php?";
+var symbianOrgNewReplyUrl = symbianOrgBaseUrl+"/forum/newreply.php?";
+var symbianOrgLoginUrl = symbianOrgBaseUrlSsl+"/main/user_profile/login.php";
+var symbianOrgLoginUsernameField = "username";
+var symbianOrgLoginPasswordField = "password";
+var forumUsername = null ;
+var forumPassword = null;
+
+// Feed name, URL etc for forums
+var forumFeedName = "Symbian.org Forums";
+var forumFeedURL = symbianOrgBaseUrl+ "/forum/external.php?type=rss2"; //&fulldesc=1&lastpost=1
+var forumsForumSpecQuery = "&forumid=";
+var forumFeedUpdateFrequency = -1;
+
+var forumGroupsUrl = symbianOrgBaseUrl+ "/rss/forum.php?type=groups";
+var forumsListUrl = symbianOrgBaseUrl+ "/rss/forum.php?type=forums&group=";
+var forumThreadUrl = symbianOrgBaseUrl+ "/rss/forum.php?type=threadmsgs&threadid=";
+
+// Wiki url etc
+var wikiFeedName = "New on Symbian.org Wiki";
+var wikiFeedUrl = symbianOrgBaseUrl+"/wiki/index.php?title=Special:NewPages&feed=rss";
+var wikiBaseUrl = symbianOrgBaseUrl+"/wiki/index.php";
+
+// Update variables
+var myversion = "1.0rc3";
+var versionWikiPageUrl = wikiBaseUrl + "/Symbian.org_WRT_Widget";
+var versionWikiPageString = "Current widget version is [";
+var downloadUrl = symbianOrgBaseUrl + "/wiki/images/c/c5/Symbian.org.wgz";
+
+// UI elements
+
+// blog / forum instances
+// all are SOScreen subclasses
+var home; // home screen
+var blog; // RSSReader showing blog
+var wiki; // RSSReader showing wiki
+var bugzila; // RSSReader showing bugzilla feeds
+var forumGroups; // RSSReader showing list of forum groups
+var settings;
+var about;
+
+// currently showing SOScreen
+var currentScreen = null;
+
+// Controls for the settings view
+var forumUsernameControl;
+var forumPasswordControl;
+
+// Constants for menu item identifiers.
+var MENU_ITEM_SETTINGS = 0;
+var MENU_ITEM_REFRESH = 1;
+var MENU_ITEM_ABOUT = 2;
+var MENU_ITEM_CHECK_UPDATE = 3;
+
+// Flag indicating weather the web site login has been initiated
+var loginInitiated = false;
+var loginInitiatedCallback = null;
+
+
+var widgetHomepage = symbianOrgBaseUrl + "/wiki/index.php?title=Symbian.org_WRT_Widget&action=render";
+var aboutText = "<strong>Symbian.org "+myversion+"</strong><br>"
+ + "Symbian.org WRT Widget is a Web Runtime application which allows mobile "
+ + "access to Symbian Foundation Forums, Blog, Wiki and Bugzilla. <br>"
+ + "For more information and updates check <div class=FeedItemLink>"
+ + "<a href=\"JavaScript:void(0)\" onclick=\"openURL('"
+ + widgetHomepage
+ + "'); return false;\">"
+ +" Symbian.org Widget Homepage </a> </div><p>"
+ + "Credits: Ivan Litovski, Ryan Grentz, James Mentz";
+
+
+// Called from the onload event handler to initialize the widget.
+function init() {
+
+ // set tab-navigation mode and show softkeys
+ // (only if we are in the WRT environment)
+ if (window.widget) {
+ widget.setNavigationEnabled(false);
+ window.menu.showSoftkeys();
+ // create menu
+ var settingsMenuItem = new MenuItem("Settings", MENU_ITEM_SETTINGS);
+ settingsMenuItem.onSelect = menuItemSelected;
+ menu.append(settingsMenuItem);
+ var refreshMenuItem = new MenuItem("Refresh", MENU_ITEM_REFRESH);
+ refreshMenuItem.onSelect = menuItemSelected;
+ menu.append(refreshMenuItem);
+ var aboutMenuItem = new MenuItem("About", MENU_ITEM_ABOUT);
+ aboutMenuItem.onSelect = menuItemSelected;
+ menu.append(aboutMenuItem);
+ var updateMenuItem = new MenuItem("Check for updates", MENU_ITEM_CHECK_UPDATE);
+ updateMenuItem.onSelect = menuItemSelected;
+ menu.append(updateMenuItem);
+ }
+
+ // load prefs
+ if (!forumUsername || !forumPassword) {
+ loadPreferences();
+ }
+
+ // create UI manager
+ uiManager = new UIManager();
+
+ // Create the home view
+ home = new ListView(null, "<img src=logo.png>");
+
+ // add forums button
+ var forumsButton = new NavigationButton(1, "right.gif", "Forums")
+ forumsButton.addEventListener("ActionPerformed", function(){forumGroups.show();});
+ home.addControl(forumsButton);
+
+ // add blogs button
+ var blogsButton = new NavigationButton(2, "right.gif", "Blogs")
+ blogsButton.addEventListener("ActionPerformed", function(){blog.show();});
+ home.addControl(blogsButton);
+
+ // add wiki button
+ var wikiButton = new NavigationButton(3, "right.gif", "Wiki")
+ wikiButton.addEventListener("ActionPerformed", function(){wiki.show();});
+ home.addControl(wikiButton);
+
+ // add bugzilla button
+ var bugzillaButton = new NavigationButton(3, "right.gif", "Bugzilla")
+ bugzillaButton.addEventListener("ActionPerformed", function(){login(function(){bugzilla.show();});});
+ home.addControl(bugzillaButton);
+
+ // soft keys
+ home.setupSoftKeys = function() {
+ if (window.widget) {
+ menu.setRightSoftkeyLabel("Exit", function(){window.close();});
+ }
+ }
+
+ // create blog screen
+ blog = new RssReader(blogFeedName, blogFeedUrl, null, home, null);
+
+ // create wiki screen
+ wiki = new RssReader(wikiFeedName, wikiFeedUrl, new ButtonFeedPresenter(null), home, null);
+
+ // wiki feed contains full article text for many articles
+ // this takes up a _lot_ of memory. Also we don't
+ // really want the full text at the stage when we want a list
+ // of recent articles.
+ wiki.ignoreContent = true;
+
+ wiki.maxItems = 20;
+
+ bugzilla = new BugzillaSearchPanel(home);
+
+ // create the top level forums screen - list of forum groups
+ // forumsGroup, forum and thread screens are dynamically generated by forumGroups
+ forumGroups = new RssReader("Forums", forumGroupsUrl, new ForumGroupsFeedPresenter(null), home, forumGroupsResponseParser);
+
+ // create settings view
+ settings = new ListView(null, createCaption("Settings"));
+ settings.previousView = home;
+
+ var settingsIntroLabel = new Label(null, null,
+ "In order to access all site features, you must login. "
+ + "If you have not registered yet, please click the 'Register' button below.");
+
+ settings.addControl(settingsIntroLabel);
+ // forum username control
+ forumUsernameControl = new TextField('forumUsername', "Symbian.org username", forumUsername?forumUsername:"");
+ settings.addControl(forumUsernameControl);
+
+ // forum password control
+ forumPasswordControl = new TextField('forumPassword', "Symbian.org password", forumPassword?forumPassword:"", true);
+ settings.addControl(forumPasswordControl);
+
+ // save settings button
+ settingsSaveButton = new FormButton(null, "Save");
+ settingsSaveButton.addEventListener("ActionPerformed", saveSettingsClicked);
+ settings.addControl(settingsSaveButton);
+
+
+ // cancel settings button
+ var settingsRegisterButton = new FormButton(null, "Register");
+ settingsRegisterButton.addEventListener("ActionPerformed", function(){openURL(registrationURL);});
+ settings.addControl(settingsRegisterButton);
+
+ // cancel settings button
+ settingsCancelButton = new FormButton(null, "Cancel");
+ settingsCancelButton.addEventListener("ActionPerformed", function(){settings.goBack();});
+ settings.addControl(settingsCancelButton);
+
+ //Create about view
+ about = new ListView(null, createCaption("Symbian.org"));
+ about.previousView = home;
+ // About label control
+ aboutLabel = new ContentPanel(null, null, null, true);
+ aboutLabel.setCaption("About this Widget");
+ aboutLabel.setContent(aboutText);
+ aboutLabel.setExpanded(true);
+ about.addControl(aboutLabel);
+
+ home.show();
+ login(null);
+}
+
+// Callback for when menu items are selected.
+function menuItemSelected(id) {
+ var currentView = uiManager.getView();
+ switch (id) {
+ case MENU_ITEM_SETTINGS:
+ if ( currentView == settings || currentView == about) {
+ settings.previousView = home;
+ } else {
+ settings.previousView = currentView;
+ }
+ uiManager.hideNotification();
+ settings.show();
+ break;
+ case MENU_ITEM_REFRESH:
+ currentView.update(true);
+ break;
+ case MENU_ITEM_CHECK_UPDATE:
+ checkForUpdates();
+ break;
+ case MENU_ITEM_ABOUT:
+ if ( currentView == settings || currentView == about) {
+ about.previousView = home;
+ } else {
+ about.previousView = currentView;
+ }
+ about.show();
+ break;
+ }
+}
+
+// Loads widget preferences.
+function loadPreferences() {
+ if (window.widget) {
+ // load settings from widget preferences store
+ forumUsername = widget.preferenceForKey("forumUsername");
+ forumPassword = widget.preferenceForKey("forumPassword");
+ }
+}
+
+// Loads widget preferences.
+function savePreferences() {
+ if (window.widget) {
+ // save settings in widget preferences store
+ widget.setPreferenceForKey(forumUsername, "forumUsername");
+ widget.setPreferenceForKey(forumPassword, "forumPassword");
+ }
+}
+
+// Callback for settings view save button.
+function saveSettingsClicked() {
+ forumUsername = forumUsernameControl.getText();
+ forumPassword = forumPasswordControl.getText();
+
+ // save preferences
+ savePreferences();
+
+ settings.goBack();
+
+ if ( loginInitiated ) {
+ login(loginInitiatedCallback);
+ }
+}
+
+// Opens a URL in a separate browser window
+function openURL(url) {
+ if (window.widget) {
+ // in WRT
+ widget.openURL(url);
+ } else {
+ // outside WRT
+ window.open(url, "NewWindow");
+ }
+}
+
+var updatePageAjax = null;
+
+function checkForUpdates() {
+ uiManager.showNotification(-1, "wait", "Checking for updates...", -1);
+ updatePageAjax = new Ajax();
+ updatePageAjax.onreadystatechange = checkForUpdatesStage2;
+ updatePageAjax.open('GET', versionWikiPageUrl, true);
+ updatePageAjax.send(null);
+}
+
+function checkForUpdatesStage2() {
+ if (updatePageAjax.readyState == 4) {
+ // extract version number
+ var content = updatePageAjax.responseText;
+ var ind = content.indexOf(versionWikiPageString);
+ if ( ind == -1 ) {
+ uiManager.showNotification(3000, "warning", "Update failed, check manually.");
+ return;
+ }
+ ind += versionWikiPageString.length;
+ var ind2 = content.indexOf("]",ind);
+ if ( ind2 == -1 || (ind2-ind) > 10 ) {
+ uiManager.showNotification(3000, "warning", "Update failed, check manually.");
+ return;
+ }
+ var version = content.substring(ind,ind2);
+ // compare to this version
+ if ( version != myversion ) {
+ var answer = confirm("Install new version " + version + "?");
+ if (answer) {
+ // ok, we have the update
+ uiManager.hideNotification();
+ openURL(downloadUrl);
+ } else {
+ uiManager.showNotification(3000, "info", "Update cancelled.");
+ }
+ } else {
+ uiManager.showNotification(3000, "info", "Up to date!");
+ }
+ }
+}
+
+function createCaption(caption) {
+ if (caption.length > 30) {
+ caption = caption.substring(0, 30) + "...";
+ }
+ return "<table border=0>"
+ + "<tr><td><img src=titlebar.png style=\"{vertical-align:middle}\" > </td></td><td>"
+ + "<p class=ListViewCaptionText>"+ caption +"</p>"
+ + "</td></tr></table>";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/RssReader.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,137 @@
+///////////////////////////////////////////////////////////////////////////////
+// RSS Reader from WRTKit examples, modified for Symbian.org
+
+// RSS reader class
+
+function RssReader(aFeedName, aFeedUrl, aFeedPresenter, aParent, aResponseParser){
+ this.responseParser = aResponseParser;
+ this.feedUpdateBroker = null;
+ this.feedUpdateBrokerActive = false;
+ this.feedName = aFeedName;
+ this.feedURL = aFeedUrl;
+ this.feedUpdateForced = false;
+ this.feedItemControls = [];
+ this.feedLastModified = 0;
+ this.ignoreContent = false;
+ this.hasData = false;
+ this.startFromItem = 0;
+ this.maxItems = 0;
+
+ var caption = createCaption(aFeedName);
+
+ ListView.prototype.init.call(this, null, caption);
+ this.previousView = aParent;
+ if (aFeedPresenter != null) {
+ this.feedPresenter = aFeedPresenter;
+ this.feedPresenter.init(this);
+ } else {
+ this.feedPresenter = new HtmlFeedPresenter(this);
+ }
+
+ // add pre-amble items (latest posts, new thread, reply etc)
+ this.feedPresenter.addPreambleItems();
+}
+
+RssReader.prototype = new ListView(null, null);
+
+// Callback function that gets called when a feed update has completed.
+RssReader.prototype.feedUpdateCompleted = function(event){
+ // remove cancel button
+ this.setupSoftKeys();
+ if (event.status == "ok") {
+ // if there aren't any feed items yet, we'll hide the progress dialog
+
+ // check if the feed has updated
+ if (event.lastModified != this.feedLastModified) {
+ // remember the last modified timestamp
+ this.feedLastModified = event.lastModified;
+
+ // feed fetched and parsed successfully
+ this.setFeedItems(event.items);
+
+ // focus the first feed item control
+ // (but only if we are in the main view)
+ if (this.feedItemControls.length > 0 ) {
+ this.feedItemControls[0].setFocused(true);
+ }
+ }
+ uiManager.hideNotification();
+ }
+ else if (event.status != "cancelled") {
+ // show error message
+ uiManager.showNotification(3000, "warning", "Error while updating feed!<br/>(check network settings)");
+ }
+
+ // reset the broker
+ this.feedUpdateBroker = null;
+ this.feedUpdateBrokerActive = false;
+
+ // reset commanded feed update flag
+ this.feedUpdateForced = false;
+}
+
+// Removes feed items.
+RssReader.prototype.removeFeedItems = function (){
+ // remove all current feed items from the main view
+ for (var i = 0; i < this.feedItemControls.length; i++) {
+ this.removeControl(this.feedItemControls[i]);
+ }
+
+ // reset feed item control array
+ this.feedItemControls = [];
+}
+
+
+// Sets feed items.
+RssReader.prototype.setFeedItems = function (items){
+ // start by removing all current feed items
+ this.removeFeedItems();
+
+ if (items.length == 0) {
+ this.feedPresenter.showNoItems();
+ }
+ else {
+ // create new feed items and add them to the main view
+ // use feed item pool to recycle controls
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ this.feedPresenter.show(item);
+ }
+
+ }
+ this.hasData = true;
+}
+
+
+// Update feed
+RssReader.prototype.update = function(forceFeedUpdate){
+ if ( this.hasData && !forceFeedUpdate ) {
+ return;
+ }
+ this.feedUpdateForced = forceFeedUpdate;
+
+ // check if a feed update has been scheduled, if it's time to update now,
+ // and if there's no update currently in progress and if we're in the main view
+ if ((this.feedURL != null) && (!this.feedUpdateBrokerActive) ) { //&& (uiManager.getView() == this) ) {
+ // fetch the feed from the specified URL
+ this.feedUpdateBrokerActive = true;
+ this.feedUpdateBroker = new FeedUpdateBroker();
+ this.feedUpdateBroker.startFromItem = this.startFromItem;
+ this.feedUpdateBroker.maxItems = this.maxItems;
+
+ if ( this.responseParser != null ) {
+ this.feedUpdateBroker.responseParser = this.responseParser;
+ }
+ this.feedUpdateBroker.ignoreContent = this.ignoreContent;
+ this.feedUpdateBroker.fetchFeed(this.feedURL, this);
+ // allow cancelling
+ if (window.widget) {
+ var self = this;
+ menu.setRightSoftkeyLabel("Cancel", function(){
+ self.feedUpdateBroker.cancel(); self.setupSoftKeys();
+ uiManager.hideNotification();
+ });
+ }
+ uiManager.showNotification(-1, "wait", "Loading feed...", -1);
+ }
+}
Binary file Symbian.org/WRTKit/Resources/CheckBox.png has changed
Binary file Symbian.org/WRTKit/Resources/ContentPanelFoldIcons.png has changed
Binary file Symbian.org/WRTKit/Resources/ControlAssemblyBackground.png has changed
Binary file Symbian.org/WRTKit/Resources/DocumentBackground.png has changed
Binary file Symbian.org/WRTKit/Resources/FormButtonCenter.png has changed
Binary file Symbian.org/WRTKit/Resources/FormButtonLeft.png has changed
Binary file Symbian.org/WRTKit/Resources/FormButtonRight.png has changed
Binary file Symbian.org/WRTKit/Resources/ListViewCaptionBackground.png has changed
Binary file Symbian.org/WRTKit/Resources/NotificationPopupBackground.png has changed
Binary file Symbian.org/WRTKit/Resources/NotificationPopupTypeIndicator.png has changed
Binary file Symbian.org/WRTKit/Resources/ProgressBarUnknown.gif has changed
Binary file Symbian.org/WRTKit/Resources/RadioButton.png has changed
Binary file Symbian.org/WRTKit/Resources/ScrollbarThumbBottom.png has changed
Binary file Symbian.org/WRTKit/Resources/ScrollbarThumbMiddle.png has changed
Binary file Symbian.org/WRTKit/Resources/ScrollbarThumbTop.png has changed
Binary file Symbian.org/WRTKit/Resources/ScrollbarTrackBottom.png has changed
Binary file Symbian.org/WRTKit/Resources/ScrollbarTrackMiddle.png has changed
Binary file Symbian.org/WRTKit/Resources/ScrollbarTrackTop.png has changed
Binary file Symbian.org/WRTKit/Resources/SeparatorCenter.png has changed
Binary file Symbian.org/WRTKit/Resources/SeparatorLeft.png has changed
Binary file Symbian.org/WRTKit/Resources/SeparatorRight.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/Resources/UI.css Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,912 @@
+ /*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+/******************************************************************************/
+/* Definition of visuals for the WRTKit user interface toolkit */
+/******************************************************************************/
+
+/******************************************************************************/
+/* Document body rules */
+
+body {
+ margin: 0px;
+ background: url("DocumentBackground.png") repeat; /* repeat-x fixed; */
+ font: normal 12px Arial, sans-serif;
+ color: rgb(0,0,0);
+}
+
+
+/******************************************************************************/
+/* Override default WRT styling for HTML form controls */
+
+/* Textarea when focused */
+textarea:focus {
+ outline: none;
+}
+
+/* Textarea when hovering */
+textarea:hover {
+ outline: none;
+}
+
+/* Select elements when focused */
+select:focus {
+ outline: none;
+}
+
+/* Select elements when hovering */
+select:hover {
+ outline: none;
+}
+
+/* Input elements when focused */
+input:focus {
+ outline: none;
+}
+
+/* Input elements when hovering */
+input:hover {
+ outline: none;
+}
+
+/* Link elements */
+a {
+ text-decoration: none;
+ color: rgb(0,0,0);
+}
+
+/* Links when focused */
+a:focus {
+ background: none;
+ outline: none;
+}
+
+/* Links when hovering */
+a:hover {
+ background: none;
+ outline: none;
+}
+
+
+/******************************************************************************/
+/* Rules for default view and document scrollbar containers */
+
+/* Default view container rules */
+.ViewContainer {
+ margin: 0px 0px 0px 0px;
+}
+
+/* Default document scrollbar container rules */
+.DocumentScrollbarContainer {
+ position: fixed;
+ right: 0px;
+ top: 0px;
+ height: 100%;
+ width: 7px;
+}
+
+
+/******************************************************************************/
+/* View style rules */
+
+/* Rules for the list view */
+.ListView {
+ margin: 0px 0px 0px 0px;
+}
+
+/* Rules for the list view caption */
+.ListViewCaption {
+ background: url("ListViewCaptionBackground.png");
+ height: 35px;
+}
+
+/* Rules for the list view caption text */
+.ListViewCaptionText {
+ font-size: 18px;
+ font-weight: bold;
+ padding: 7px 0px 0px 11px;
+}
+
+/* Rules for the list view control list element */
+.ListViewControlList {
+ margin: 1px 10px 1px 3px;
+}
+
+
+/******************************************************************************/
+/* Control style rules */
+
+/* Rules for control root element (rootElement) */
+.Control {
+
+}
+
+/* Control assembly rules (assemblyElement) */
+.ControlAssembly {
+ background: url("ControlAssemblyBackground.png") repeat-x;
+ padding: 1px 5px;
+}
+
+/* Control assembly in normal state */
+.ControlAssemblyNormal {
+ background-position: 0px 0px;
+}
+
+/* Control assembly in focused state */
+.ControlAssemblyFocus {
+ background-position: 0px -250px;
+}
+
+/* Control assembly in hovering state */
+.ControlAssemblyHover {
+ background-position: 0px -500px;
+}
+
+/* Control assembly in disabled state */
+.ControlAssemblyDisabled {
+ background-position: 0px 0px;
+}
+
+/* Caption for controls (captionElement) */
+.ControlCaption {
+ font-weight: bold;
+ padding: 3px 0px 0px 3px;
+}
+
+/* Caption for controls in normal state */
+.ControlCaptionNormal {
+
+}
+
+/* Caption for controls when focused */
+.ControlCaptionFocus {
+ color: rgb(0,0,0);
+}
+
+/* Caption for controls when hovering */
+.ControlCaptionHover {
+
+}
+
+/* Caption for controls when disabled */
+.ControlCaptionDisabled {
+ color: rgb(125,125,125);
+}
+
+/* Control element rules (controlElement) */
+.ControlElement {
+ padding: 3px 3px 3px 3px;
+}
+
+/******************************************************************************/
+/* Label */
+
+/* Rules for the text value of a Label control */
+.LabelText {
+
+}
+
+
+/******************************************************************************/
+/* ContentPanel */
+
+/* Caption area rules for non-foldable content panels */
+.ContentPanelCaptionNonFoldable {
+ padding: 3px 0px 0px 3px;
+}
+
+/* Caption area rules for foldable content panels */
+.ContentPanelCaptionFoldable {
+ padding: 4px 0px 3px 3px;
+}
+
+/* Rules for fold toggling element in content panel */
+.ContentPanelFoldToggle {
+ background: url("ContentPanelFoldIcons.png") no-repeat;
+ padding-left: 16px;
+}
+
+/* Collapsed fold */
+.ContentPanelFoldToggleCollapsed {
+ background-position: 0px 0px;
+}
+
+/* Expanded fold */
+.ContentPanelFoldToggleExpanded {
+ background-position: 0px -100px;
+}
+
+/* Rules for the content panel caption text */
+.ContentPanelCaptionText {
+ font-weight: bold;
+}
+
+/* Caption text for content panel in normal state */
+.ContentPanelCaptionTextNormal {
+
+}
+
+/* Caption text for content panel when focused */
+.ContentPanelCaptionTextFocus {
+ color: rgb(0,0,0);
+}
+
+/* Caption text for content panel when hovering */
+.ContentPanelCaptionTextHover {
+
+}
+
+/* Caption text for content panel when disabled */
+.ContentPanelCaptionTextDisabled {
+ color: rgb(125,125,125);
+}
+
+/* Rules for content in the content panel */
+.ContentPanelContent {
+ padding: 2px 2px 2px 8px;
+}
+
+
+/******************************************************************************/
+/* FormButton */
+
+/* Rules for form button */
+.FormButton {
+
+}
+
+/* Rules for form button control element */
+.FormButtonControlElement {
+
+}
+
+/* Rules for form button table (table) */
+.FormButtonTable {
+ width: 100%;
+ border-spacing: 0px;
+ padding: 0px;
+ table-layout: fixed;
+}
+
+/* Form button row (tr) */
+.FormButtonRow {
+ padding: 0px;
+}
+
+/* Rules for form button left cell (td) */
+.FormButtonLeftCell {
+ width: 8px;
+ height: 26px;
+ background: url("FormButtonLeft.png") no-repeat;
+ padding: 0px;
+}
+
+/* Rules for form button center cell (td) */
+.FormButtonCenterCell {
+ height: 26px;
+ background: url("FormButtonCenter.png") repeat-x;
+ padding: 0px;
+ vertical-align: middle;
+ text-align: center;
+}
+
+/* Rules for form button right cell (td) */
+.FormButtonRightCell {
+ width: 8px;
+ height: 26px;
+ background: url("FormButtonRight.png") no-repeat;
+ padding: 0px;
+}
+
+/* Rules for form button left cell in normal state (td) */
+.FormButtonLeftCellNormal {
+ background-position: 0px 0px;
+}
+
+/* Rules for form button left cell in focused state (td) */
+.FormButtonLeftCellFocus {
+ background-position: 0px -50px;
+}
+
+/* Rules for form button left cell in hover state (td) */
+.FormButtonLeftCellHover {
+ background-position: 0px -100px;
+}
+
+/* Rules for form button left cell in disabled state (td) */
+.FormButtonLeftCellDisabled {
+ background-position: 0px -150px;
+}
+
+/* Rules for form button center cell in normal state (td) */
+.FormButtonCenterCellNormal {
+ background-position: 0px 0px;
+}
+
+/* Rules for form button center cell in focused state (td) */
+.FormButtonCenterCellFocus {
+ background-position: 0px -50px;
+}
+
+/* Rules for form button center cell in hover state (td) */
+.FormButtonCenterCellHover {
+ background-position: 0px -100px;
+}
+
+/* Rules for form button center cell in disabled state (td) */
+.FormButtonCenterCellDisabled {
+ background-position: 0px -150px;
+}
+
+/* Rules for form button left cell in normal state (td) */
+.FormButtonRightCellNormal {
+ background-position: 0px 0px;
+}
+
+/* Rules for form button left cell in focused state (td) */
+.FormButtonRightCellFocus {
+ background-position: 0px -50px;
+}
+
+/* Rules for form button left cell in hover state (td) */
+.FormButtonRightCellHover {
+ background-position: 0px -100px;
+}
+
+/* Rules for form button left cell in disabled state (td) */
+.FormButtonRightCellDisabled {
+ background-position: 0px -150px;
+}
+
+/* Rules for form button text */
+.FormButtonText {
+ font-weight: bold;
+}
+
+/* Form button text in normal state */
+.FormButtonTextNormal {
+ color: rgb(255,255,255);
+}
+
+/* Form button text when focused */
+.FormButtonTextFocus {
+ color: rgb(255,255,255);
+}
+
+/* Form button text when hovering */
+.FormButtonTextHover {
+ color: rgb(255,255,255);
+}
+
+/* Form button text when disabled */
+.FormButtonTextDisabled {
+ color: rgb(200,200,200);
+}
+
+
+/******************************************************************************/
+/* NavigationButton */
+
+/* Rules for navigation button */
+.NavigationButton {
+
+}
+
+/* Rules for navigation button control element */
+.NavigationButtonControlElement {
+ padding: 3px 3px 3px 3px;
+}
+
+/* Rules for navigation button table (table) */
+.NavigationButtonTable {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+/* Navigation button row (tr) */
+.NavigationButtonRow {
+ padding: 0px;
+}
+
+/* Rules for navigation button image cell (td) */
+.NavigationButtonImageCell {
+ line-height: 1px;
+ font-size: 1px;
+ vertical-align: middle;
+}
+
+/* Rules for navigation button text cell (td) */
+.NavigationButtonTextCell {
+ vertical-align: middle;
+ padding: 0px;
+}
+
+/* Rules for navigation button image */
+.NavigationButtonImage {
+ padding: 0px 5px 0px 0px;
+}
+
+/* Rules for navigation button text */
+.NavigationButtonText {
+ font-weight: bold;
+}
+
+/* Navigation button text in normal state */
+.NavigationButtonTextNormal {
+
+}
+
+/* Navigation button text when focused */
+.NavigationButtonTextFocus {
+ color: rgb(0,0,0);
+}
+
+/* Navigation button text when hovering */
+.NavigationButtonTextHover {
+
+}
+
+/* Navigation button text when disabled */
+.NavigationButtonTextDisabled {
+ color: rgb(125,125,125);
+}
+
+
+/******************************************************************************/
+/* TextField */
+
+/* Rules for textField */
+.TextField {
+ width: 100%;
+ border: 1px solid rgb(0,0,0);
+ background: rgb(255,255,255);
+ margin: 0px 0px 3px 0px;
+}
+
+/* TextField in normal state */
+.TextFieldNormal {
+
+}
+
+/* TextField in focus state */
+.TextFieldFocus {
+
+}
+
+/* TextField in hover state */
+.TextFieldHover {
+
+}
+
+/* TextField in disabled state */
+.TextFieldDisabled {
+ color: rgb(50,50,50);
+ background: rgb(200,200,200);
+}
+
+
+/******************************************************************************/
+/* TextArea */
+
+/* Rules for TextArea */
+.TextArea {
+ width: 100%;
+ border: 1px solid rgb(0,0,0);
+ background: rgb(255,255,255);
+ margin: 0px 0px 3px 0px;
+}
+
+/* TextArea in normal state */
+.TextAreaNormal {
+
+}
+
+/* TextArea in focus state */
+.TextAreaFocus {
+
+}
+
+/* TextArea in hover state */
+.TextAreaHover {
+
+}
+
+/* TextArea in disabled state */
+.TextAreaDisabled {
+ color: rgb(50,50,50);
+ background: rgb(200,200,200);
+}
+
+
+/******************************************************************************/
+/* Separator */
+
+/* Rules for Separator (table) */
+.Separator {
+ width: 100%;
+ padding: 0px;
+ border-spacing: 0px;
+ table-layout: fixed;
+ margin: 3px 0px;
+}
+
+/* Separator row (tr) */
+.SeparatorRow {
+ padding: 0px;
+}
+
+/* Separator left cell (td) */
+.SeparatorLeftCell {
+ width: 5px;
+ height: 2px;
+ background: url("SeparatorLeft.png") no-repeat;
+ padding: 0px;
+}
+
+/* Separator center cell (td) */
+.SeparatorCenterCell {
+ height: 2px;
+ background: url("SeparatorCenter.png") repeat-x;
+ padding: 0px;
+}
+
+/* Separator right cell (td) */
+.SeparatorRightCell {
+ width: 6px;
+ height: 2px;
+ background: url("SeparatorRight.png") no-repeat;
+ padding: 0px;
+}
+
+
+/******************************************************************************/
+/* SelectionMenu */
+
+/* Rules for SelectionMenu select element */
+.SelectionMenu {
+ width: 100%;
+ border: 1px solid rgb(0,0,0);
+ background: rgb(255,255,255);
+ margin: 0px 0px 3px 0px;
+}
+
+/* SelectionMenu in normal state */
+.SelectionMenuNormal {
+
+}
+
+/* SelectionMenu in focus state */
+.SelectionMenuFocus {
+
+}
+
+/* SelectionMenu in hover state */
+.SelectionMenuHover {
+
+}
+
+/* SelectionMenu in disabled state */
+.SelectionMenuDisabled {
+ color: rgb(50,50,50);
+ background: rgb(200,200,200);
+}
+
+/* Rules for SelectionMenu option elements */
+.SelectionMenuOption {
+ background: rgb(255,255,255);
+}
+
+/* SelectionMenu option in normal state */
+.SelectionMenuOptionNormal {
+
+}
+
+/* SelectionMenu option in focus state */
+.SelectionMenuOptionFocus {
+
+}
+
+/* SelectionMenu option in hover state */
+.SelectionMenuOptionHover {
+
+}
+
+/* SelectionMenu option in disabled state */
+.SelectionMenuOptionDisabled {
+ color: rgb(50,50,50);
+ background: rgb(200,200,200);
+}
+
+
+/******************************************************************************/
+/* SelectionList */
+
+/* SelectionList option list element */
+.SelectionList {
+
+}
+
+/* SelectionList option list element in normal state */
+.SelectionListNormal {
+
+}
+
+/* SelectionList option list element in focus state */
+.SelectionListFocus {
+
+}
+
+/* SelectionList option list element in hover state */
+.SelectionListHover {
+
+}
+
+/* SelectionList option list element in disabled state */
+.SelectionListDisabled {
+
+}
+
+/* SelectionList option element in single selection mode */
+.SelectionListOptionSingle {
+ padding-left: 19px;
+ background: url("RadioButton.png") no-repeat;
+ height: 16px;
+}
+
+/* SelectionList option element in single selection mode, unchecked normal state */
+.SelectionListOptionSingleUncheckedNormal {
+ background-position: 0px 0px;
+}
+
+/* SelectionList option element in single selection mode, unchecked focus state */
+.SelectionListOptionSingleUncheckedFocus {
+ background-position: 0px -50px;
+}
+
+/* SelectionList option element in single selection mode, unchecked diabled state */
+.SelectionListOptionSingleUncheckedDisabled {
+ background-position: 0px -100px;
+}
+
+/* SelectionList option element in single selection mode, checked normal state */
+.SelectionListOptionSingleCheckedNormal {
+ background-position: 0px -150px;
+}
+
+/* SelectionList option element in single selection mode, checked focus state */
+.SelectionListOptionSingleCheckedFocus {
+ background-position: 0px -200px;
+}
+
+/* SelectionList option element in single selection mode, checked diabled state */
+.SelectionListOptionSingleCheckedDisabled {
+ background-position: 0px -250px;
+}
+
+/* SelectionList option element in multi selection mode */
+.SelectionListOptionMulti {
+ padding-left: 19px;
+ background: url("CheckBox.png") no-repeat;
+ height: 16px;
+}
+
+/* SelectionList option element in multi selection mode, unchecked normal state */
+.SelectionListOptionMultiUncheckedNormal {
+ background-position: 0px 0px;
+}
+
+/* SelectionList option element in multi selection mode, unchecked focus state */
+.SelectionListOptionMultiUncheckedFocus {
+ background-position: 0px -50px;
+}
+
+/* SelectionList option element in multi selection mode, unchecked diabled state */
+.SelectionListOptionMultiUncheckedDisabled {
+ background-position: 0px -100px;
+}
+
+/* SelectionList option element in multi selection mode, checked normal state */
+.SelectionListOptionMultiCheckedNormal {
+ background-position: 0px -150px;
+}
+
+/* SelectionList option element in multi selection mode, checked focus state */
+.SelectionListOptionMultiCheckedFocus {
+ background-position: 0px -200px;
+}
+
+/* SelectionList option element in multi selection mode, checked diabled state */
+.SelectionListOptionMultiCheckedDisabled {
+ background-position: 0px -250px;
+}
+
+/* SelectionList option text */
+.SelectionListOptionText {
+
+}
+
+/* SelectionList option text in normal state */
+.SelectionListOptionTextNormal {
+
+}
+
+/* SelectionList option text in focus state */
+.SelectionListOptionTextFocus {
+ color: rgb(0,0,0);
+}
+
+/* SelectionList option text in hover state */
+.SelectionListOptionTextHover {
+
+}
+
+/* SelectionList option text in disabled state */
+.SelectionListOptionTextDisabled {
+ color: rgb(125,125,125);
+}
+
+
+/******************************************************************************/
+/* Scrollbar */
+
+/* Scrollbar root element */
+.Scrollbar {
+ position: absolute;
+ height: 100%;
+ width: 7px;
+}
+
+/* Top portion of scrollbar track */
+.ScrollbarTrackTop {
+ position: absolute;
+ background: url("ScrollbarTrackTop.png") no-repeat;
+ width: 7px;
+ height: 4px;
+}
+
+/* Middle portion of scrollbar track */
+.ScrollbarTrackMiddle {
+ position: absolute;
+ background: url("ScrollbarTrackMiddle.png") repeat-y;
+ width: 7px;
+}
+
+/* Bottom portion of scrollbar track */
+.ScrollbarTrackBottom {
+ position: absolute;
+ background: url("ScrollbarTrackBottom.png") no-repeat;
+ width: 7px;
+ height: 4px;
+}
+
+/* Top portion of scrollbar thumb */
+.ScrollbarThumbTop {
+ position: absolute;
+ background: url("ScrollbarThumbTop.png") no-repeat;
+ width: 7px;
+ height: 5px;
+}
+
+/* Middle portion of scrollbar thumb */
+.ScrollbarThumbMiddle {
+ position: absolute;
+ background: url("ScrollbarThumbMiddle.png") repeat-y;
+ width: 7px;
+}
+
+/* Bottom portion of scrollbar thumb */
+.ScrollbarThumbBottom {
+ position: absolute;
+ background: url("ScrollbarThumbBottom.png") no-repeat;
+ width: 7px;
+ height: 5px;
+}
+
+
+/******************************************************************************/
+/* NotificationPopup */
+
+/* Container that defines the area for the popup dialog */
+.NotificationPopupContainer {
+ position: fixed;
+ bottom: 0px;
+ left: 50%;
+ margin-left: -115px;
+ width: 230px;
+ height: 85px;
+}
+
+/* Notification popup dialog */
+.NotificationPopup {
+ position: absolute;
+ width: 230px;
+ height: 85px;
+ background: url("NotificationPopupBackground.png") repeat-x;
+ border: 1px solid rgb(0,0,0);
+}
+
+/* Notification type indicator */
+.NotificationPopupTypeIndicator {
+ position: absolute;
+ left: 195px;
+ top: 10px;
+ width: 24px;
+ height: 34px;
+ background: url("NotificationPopupTypeIndicator.png") no-repeat;
+}
+
+/* Notification type indicator for notifications of undefined type */
+.NotificationPopupTypeIndicatorNone {
+ background-position: 0px 0px;
+}
+
+/* Notification type indicator for info notifications */
+.NotificationPopupTypeIndicatorInfo {
+ background-position: 0px -50px;
+}
+
+/* Notification type indicator for warning notifications */
+.NotificationPopupTypeIndicatorWarning {
+ background-position: 0px -100px;
+}
+
+/* Notification type indicator for wait notifications */
+.NotificationPopupTypeIndicatorWait {
+ background-position: 0px -150px;
+}
+
+/* Notification text area */
+.NotificationPopupText {
+ position: absolute;
+ left: 10px;
+ top: 8px;
+ width: 180px;
+ height: 50px;
+}
+
+/* Progress bar */
+.NotificationPopupProgressBar {
+ position: absolute;
+ left: 6px;
+ top: 60px;
+ width: 218px;
+ height: 16px;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/ActionControl.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,144 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (ÒNokiaÓ) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under NokiaÕs copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The ActionControl class is an abstract base class for action controls like
+// buttons. Don't use ActionControl directly.
+
+// Constructor.
+function ActionControl(id, caption) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption);
+ }
+}
+
+// ActionControl inherits from Control.
+ActionControl.prototype = new Control(UI_NO_INIT_ID);
+
+// Reference to the button element.
+ActionControl.prototype.buttonElement = null;
+
+// Reference to the link element.
+ActionControl.prototype.linkElement = null;
+
+// Enabled status.
+ActionControl.prototype.enabled = false;
+
+// Initializer - called from constructor.
+ActionControl.prototype.init = function(id, caption) {
+ uiLogger.debug("ActionControl.init(" + id + ", " + caption + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, caption);
+
+ // the control defaults to enabled
+ this.enabled = true;
+}
+
+// Common event listeners hookup function called from subclasses.
+ActionControl.prototype.bindActionControlListeners = function() {
+ var self = this;
+ this.linkElement.addEventListener("focus", function() { self.focusStateChanged(true); }, false);
+ this.linkElement.addEventListener("blur", function() { self.focusStateChanged(false); }, false);
+ this.buttonElement.addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
+ this.buttonElement.addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
+ this.buttonElement.addEventListener("mousedown", function(event) {
+ self.controlClicked(event);
+ event.stopPropagation();
+ event.preventDefault();
+ }, true);
+ this.buttonElement.addEventListener("keydown", function(event) {
+ // center and enter trigger the action
+ if (event.keyCode == 0 || event.keyCode == 13) {
+ self.controlClicked();
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }, true);
+}
+
+// Returns the enabled state.
+ActionControl.prototype.isEnabled = function() {
+ return this.enabled;
+}
+
+// Sets the enabled state.
+ActionControl.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("ActionControl.setEnabled(" + enabled + ")");
+ // switch the state
+ this.enabled = enabled;
+}
+
+// Sets the focused state for the control.
+// Note: This may not always succeed.
+ActionControl.prototype.setFocused = function(focused) {
+ uiLogger.debug("ActionControl.setFocused(" + focused + ")");
+ if (this.enabled) {
+ if (focused) {
+ this.linkElement.focus();
+ } else {
+ this.linkElement.blur();
+ }
+ }
+}
+
+// Callback for clicks.
+ActionControl.prototype.controlClicked = function(event) {
+ uiLogger.debug("ActionControl.controlClicked()");
+
+ // if we're enabled then a click results in an action performed event
+ if (this.enabled) {
+ // focus when clicked
+ if (!this.focused) {
+ this.linkElement.focus();
+ }
+
+ // notify event listeners
+ this.actionPerformed(event);
+ }
+}
+
+// Callback for action performed events.
+ActionControl.prototype.actionPerformed = function(event) {
+ uiLogger.debug("ActionControl.actionPerformed()");
+ // notify event listeners
+ this.fireEvent(this.createEvent("ActionPerformed", event));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/Ajax.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,103 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// Ajax utility calss to create XmlHttpRequest object
+function Ajax()
+{
+ // xmlHttpRequest object
+ var request = null;
+
+ // branch for native XMLHttpRequest object
+ if(window.XMLHttpRequest && !(window.ActiveXObject)) {
+ try
+ {
+ request = new XMLHttpRequest();
+ try
+ {
+ // attach the Bypass code, if the browser is firefox
+ if(netscape.security.PrivilegeManager.enablePrivilege)
+ {
+ // duplicate the function
+ request._open = request.open;
+
+ // redefine the function definition
+ request.open = function(method, url, flag)
+ {
+ try
+ {
+ // Enable Universal Browser Read
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
+
+ // call the native XmlHttpRequest.open method
+ this._open(method, url, flag);
+ }catch(e)
+ {
+ // call the native XmlHttpRequest.open method
+ this._open(method, url, flag);
+ }
+ }
+ }
+ }
+ catch(e)
+ {
+ // eatup all exceptions
+ }
+ }
+ catch(e) {
+ request = null;
+ }
+ // branch for IE/Windows ActiveX version
+ } else if(window.ActiveXObject) {
+ try {
+ request = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch(e) {
+ try {
+ request = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch(e) {
+ alert('Failed to create XmlHttprequest');
+ return null;
+ }
+ }
+ }
+
+ return (request);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/ContentPanel.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,368 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The ContentPanel class is a control for displaying content. The panel
+// can be expanded and collapsed.
+
+// Constructor.
+function ContentPanel(id, caption, content, foldable, expanded) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, content, foldable, expanded);
+ }
+}
+
+// ContentPanel inherits from Control.
+ContentPanel.prototype = new Control(UI_NO_INIT_ID);
+
+// The element hierarchy in a content panel is as follows:
+//
+// rootElement
+// assemblyElement
+// captionElement
+// foldToggleElement
+// captionLinkElement
+// captionTextElement
+// contentElement
+//
+// captionTextElement is moved under foldToggleElement if disabled
+// or captionElement if not foldable
+
+// The fold toggle element used for folding content panels.
+ContentPanel.prototype.foldToggleElement = null;
+
+// The caption link element of this control.
+ContentPanel.prototype.captionLinkElement = null;
+
+// The caption text element of this control.
+ContentPanel.prototype.captionTextElement = null;
+
+// The content element of this control.
+ContentPanel.prototype.contentElement = null;
+
+// The foldable state of this control.
+ContentPanel.prototype.foldable = false;
+
+// The expanded state of this control.
+ContentPanel.prototype.expanded = false;
+
+// Enabled status.
+ContentPanel.prototype.enabled = false;
+
+// Initializer - called from constructor.
+ContentPanel.prototype.init = function(id, caption, content, foldable, expanded) {
+ uiLogger.debug("ContentPanel.init(" + id + ", " + caption + ", " + content + ", " + foldable + ", " + expanded + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, caption);
+
+ // the control defaults to enabled
+ this.enabled = true;
+
+ // create caption text element
+ this.captionTextElement = document.createElement("span");
+
+ // disconnect the control element
+ this.assemblyElement.removeChild(this.controlElement);
+
+ // set the foldable state
+ this.foldable = foldable;
+
+ // is this a foldable content panel?
+ if (foldable) {
+ // create fold toggle element
+ this.foldToggleElement = document.createElement("div");
+ this.captionElement.appendChild(this.foldToggleElement);
+
+ // create caption link and add to caption element
+ this.captionLinkElement = document.createElement("a");
+ this.captionLinkElement.href = "JavaScript:void(0)";
+ this.foldToggleElement.appendChild(this.captionLinkElement);
+
+ // add the text element to the link element
+ this.captionLinkElement.appendChild(this.captionTextElement);
+
+ // bind event listeners
+ var self = this;
+ this.captionLinkElement.addEventListener("focus", function() { self.focusStateChanged(true); }, false);
+ this.captionLinkElement.addEventListener("blur", function() { self.focusStateChanged(false); }, false);
+ this.foldToggleElement.addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
+ this.foldToggleElement.addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
+ this.foldToggleElement.addEventListener("mousedown", function(event) {
+ self.captionClicked();
+ event.stopPropagation();
+ event.preventDefault();
+ }, true);
+ this.foldToggleElement.addEventListener("keydown", function(event) {
+ // center and enter trigger the action
+ if (event.keyCode == 0 || event.keyCode == 13) {
+ self.captionClicked();
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }, true);
+
+ this.expanded = expanded;
+ } else {
+ // since this is not a foldable panel the content should be expanded
+ this.expanded = true;
+
+ // add the text element directly to the caption element
+ this.captionElement.appendChild(this.captionTextElement);
+ }
+
+ // create content element
+ this.contentElement = document.createElement("div");
+ this.contentElement.style.display = this.expanded ? "block" : "none";
+ this.rootElement.appendChild(this.contentElement);
+
+ // set caption, content and expanded state
+ this.setCaption(caption);
+ this.setContent(content);
+
+ // update style
+ this.updateStyleFromState();
+}
+
+// Returns the enabled state.
+ContentPanel.prototype.isEnabled = function() {
+ return this.enabled;
+}
+
+// Sets the enabled state.
+ContentPanel.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("ContentPanel.setEnabled(" + enabled + ")");
+
+ // bail out early if there is no change in state
+ if (this.enabled == enabled) {
+ return;
+ }
+
+ // set the enabled state
+ this.enabled = enabled;
+
+ // is this a foldable content?
+ if (this.foldable) {
+ // the caption link must be disabled
+ if (this.enabled) {
+ // diabled -> enabled
+ this.foldToggleElement.removeChild(this.captionTextElement);
+ this.foldToggleElement.appendChild(this.captionLinkElement);
+ this.captionLinkElement.appendChild(this.captionTextElement);
+ } else {
+ // enabled -> diabled
+ this.captionLinkElement.removeChild(this.captionTextElement);
+ this.foldToggleElement.removeChild(this.captionLinkElement);
+ this.foldToggleElement.appendChild(this.captionTextElement);
+ }
+ }
+
+ // update style
+ this.updateStyleFromState();
+}
+
+// Returns the caption; null if none.
+ContentPanel.prototype.getCaption = function() {
+ return this.caption;
+}
+
+// Sets the caption; null if none.
+ContentPanel.prototype.setCaption = function(caption) {
+ // bail out if the caption text element has not been created
+ // this is to prevent the superclass init calling this before
+ // we've initialized our custom caption
+ if (this.captionTextElement == null)
+ return;
+
+ uiLogger.debug("ContentPanel.setCaption(" + caption + ")");
+
+ // set the display style
+ this.captionElement.style.display = (caption == null) ? "none" : "block";
+
+ // set the caption
+ this.caption = caption;
+ this.captionTextElement.innerHTML = (caption == null) ? "" : caption;
+
+ // update style
+ this.updateStyleFromState();
+}
+
+// Returns the content.
+ContentPanel.prototype.getContent = function() {
+ return this.contentElement.innerHTML;
+}
+
+// Sets the content.
+ContentPanel.prototype.setContent = function(content) {
+ uiLogger.debug("ContentPanel.setContent(" + content + ")");
+ this.contentElement.innerHTML = (content == null) ? "" : content;
+}
+
+// Returns the focusable state for the control.
+ContentPanel.prototype.isFocusable = function() {
+ // a content panel is focusable if it's foldable and enabled
+ return (this.foldable && this.enabled);
+}
+
+// Sets the focused state for the control.
+// Note: This may not always succeed.
+ContentPanel.prototype.setFocused = function(focused) {
+ uiLogger.debug("ContentPanel.setFocused(" + focused + ")");
+ if (this.enabled && this.foldable) {
+ if (focused) {
+ this.captionLinkElement.focus();
+ } else {
+ this.captionLinkElement.blur();
+ }
+ }
+ // note that this.focused gets set as a result of focusStateChanged() being called
+ // rather than setting it explicitly here
+}
+
+// Returns the expanded state.
+ContentPanel.prototype.isExpanded = function() {
+ return this.expanded;
+}
+
+// Sets the expanded state.
+ContentPanel.prototype.setExpanded = function(expanded) {
+ uiLogger.debug("ContentPanel.setExpanded(" + expanded + ")");
+
+ // make sure only foldable content panels are folded
+ if (!this.foldable) {
+ uiLogger.warn("Cannot fold a non-foldable content panel!");
+ return;
+ }
+
+ this.expanded = expanded;
+ if (this.expanded) {
+ // expand
+ this.contentElement.style.display = "block";
+
+ // find out control top and bottom
+ var controlTop = this.getAbsoluteTop(this.rootElement);
+ var controlHeight = this.rootElement.clientHeight;
+ var controlBottom = controlTop + controlHeight;
+
+ // find out the viewport top and bottom
+ var viewportTop = window.scrollY;
+ var viewportHeight = window.innerHeight;
+ var viewportBottom = viewportTop + viewportHeight;
+
+ // make sure the control is positioned so that it can be seen
+ var overflow = controlBottom - viewportBottom;
+ if (overflow > 0) {
+ // there's overflow so we need to scroll to get the control
+ // into the viewport - however not so far that the control
+ // goes past the viewport top.
+ var distanceToTop = controlTop - viewportTop;
+ var scrollAmount = Math.min(overflow, distanceToTop);
+ window.scrollBy(0, scrollAmount);
+ }
+ } else {
+ // collapse
+ this.contentElement.style.display = "none";
+ }
+
+ // notify event listeners
+ this.fireEvent(this.createEvent("ExpandedStateChanged", this.expanded));
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Returns the absolute position (y) of the given element.
+ContentPanel.prototype.getAbsoluteTop = function(element) {
+ // traverse from element to root and add top-offset
+ // for each element we find on the way
+ var absTop = 0;
+ while (element != null) {
+ absTop += element.offsetTop;
+ element = element.offsetParent;
+ }
+ return absTop;
+}
+
+// Callback for when the caption is clicked.
+ContentPanel.prototype.captionClicked = function() {
+ uiLogger.debug("ContentPanel.captionClicked()");
+
+ // if we're enabled then a click results toggling the expanded state
+ if (this.enabled) {
+ // focus when clicked
+ if (!this.focused) {
+ this.captionLinkElement.focus();
+ }
+
+ // toggle the expanded state
+ this.setExpanded(!this.expanded);
+ }
+}
+
+// Updates the style of the control to reflects the state of the control.
+ContentPanel.prototype.updateStyleFromState = function() {
+ uiLogger.debug("ContentPanel.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set root element class name
+ this.setClassName(this.rootElement, "Control");
+
+ // set the control assembly class names
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
+
+ if (this.foldable) {
+ // foldable content panel
+ this.setClassName(this.captionElement, "ContentPanelCaptionFoldable");
+ this.setClassName(this.foldToggleElement, "ContentPanelFoldToggle ContentPanelFoldToggle" + (this.expanded ? "Expanded" : "Collapsed"));
+ } else {
+ // non-folding
+ this.setClassName(this.captionElement, "ContentPanelCaptionNonFoldable");
+ }
+
+ // set the content caption text class names
+ this.setClassName(this.captionTextElement, "ContentPanelCaptionText ContentPanelCaptionText" + stateName);
+
+ // set the content element class names
+ this.setClassName(this.contentElement, "ContentPanelContent");
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/Control.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,231 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The Control class is an abstract base class for all user interface controls.
+
+// Constructor.
+function Control(id, caption) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption);
+ }
+}
+
+// Control inherits from UIElement.
+Control.prototype = new UIElement(UI_NO_INIT_ID);
+
+// The view that control belongs to.
+Control.prototype.view = null;
+
+// Is the control focused?
+Control.prototype.focused = false;
+
+// Is the pointer over this control?
+Control.prototype.hovering = false;
+
+// The element hierarchy in a control is as follows:
+//
+// rootElement
+// assemblyElement
+// captionElement
+// controlElement
+//
+// The assembly element groups the portion of a control that typically handle
+// the visual effects for focus and hover states. Having a separate root and
+// assembly elements allows other elements to be added to a control without
+// them being affected by the CSS rules of the assembly element.
+
+// The assembly element of this control.
+Control.prototype.assemblyElement = null;
+
+// The caption of this control; null if none.
+Control.prototype.caption = null;
+
+// The caption element of this control.
+Control.prototype.captionElement = null;
+
+// The control element of this control.
+Control.prototype.controlElement = null;
+
+// Initializer - called from constructor.
+Control.prototype.init = function(id, caption) {
+ uiLogger.debug("Control.init(" + id + ", " + caption + ")");
+
+ // call superclass initializer
+ UIElement.prototype.init.call(this, id);
+
+ // create assembly, caption and control elements
+ this.assemblyElement = document.createElement("div");
+ this.captionElement = document.createElement("div");
+ this.assemblyElement.appendChild(this.captionElement);
+ this.controlElement = document.createElement("div");
+ this.assemblyElement.appendChild(this.controlElement);
+ this.rootElement.appendChild(this.assemblyElement);
+
+ // set the caption
+ // style is not updated because the subclass will update the style later
+ // when it has completely initialized the component
+ this.setCaption(caption, true);
+}
+
+// Returns the caption; null if none.
+Control.prototype.getCaption = function() {
+ return this.caption;
+}
+
+// Sets the caption; null if none.
+Control.prototype.setCaption = function(caption, noStyleUpdate) {
+ uiLogger.debug("Control.setCaption(" + caption + ")");
+
+ // set the display style
+ this.captionElement.style.display = (caption == null) ? "none" : "block";
+
+ // set the caption
+ this.caption = caption;
+ this.captionElement.innerHTML = (caption == null) ? "" : caption;
+
+ // update style
+ if (!noStyleUpdate) {
+ this.updateStyleFromState();
+ }
+}
+
+// Returns the enabled state.
+// Override this in subclasses as required to implement the state change.
+Control.prototype.isEnabled = function() {
+ return false;
+}
+
+// Sets the enabled state.
+// Override this in subclasses as required to implement the state change.
+Control.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("Control.setEnabled(" + enabled + ")");
+}
+
+// Returns the focusable state for the control.
+// Defaults focusable if enabled - override this in subclasses as required.
+Control.prototype.isFocusable = function() {
+ return this.isEnabled();
+}
+
+// Returns the focused state for the control.
+Control.prototype.isFocused = function() {
+ return this.focused;
+}
+
+// Sets the focused state for the control.
+// Note: This may not always succeed.
+// Override this in subclasses as required to implement the state change.
+Control.prototype.setFocused = function(focused) {
+ uiLogger.debug("Control.setFocused(" + focused + ")");
+ // note that this.focused gets set as a result of focusStateChanged() being called
+ // rather than setting it explicitly here
+}
+
+// Called when the focus state has changed for this control.
+Control.prototype.focusStateChanged = function(focused) {
+ uiLogger.debug("Control.focusStateChanged(" + focused + ")");
+ if (this.focused != focused) {
+ this.focused = focused;
+
+ // let the view know about the focus change
+ if (this.view != null) {
+ this.view.focusedControlChanged(focused ? this : null);
+ }
+
+ // update the style from the current state
+ this.updateStyleFromState();
+
+ // notify event listeners
+ this.fireEvent(this.createEvent("FocusStateChanged", focused));
+ }
+}
+
+// Called when the hover state has changed for this control.
+Control.prototype.hoverStateChanged = function(hovering) {
+ uiLogger.debug("Control.hoverStateChanged(" + hovering + ")");
+ if (this.hovering != hovering) {
+ this.hovering = hovering;
+
+ // update the style from the current state
+ this.updateStyleFromState();
+
+ // notify event listeners
+ this.fireEvent(this.createEvent("HoverStateChanged", hovering));
+ }
+}
+
+// Helper method that returns the state name for the current state.
+Control.prototype.getStyleStateName = function() {
+ var focusable = this.isFocusable();
+ if (focusable && this.focused) {
+ return "Focus";
+ } else if (focusable && this.hovering) {
+ return "Hover";
+ } else if (!this.isEnabled()) {
+ return "Disabled";
+ } else {
+ return "Normal";
+ }
+}
+
+// Resets the state tracking for focus and hover.
+// Override this in subclasses as required to implement the state reset.
+Control.prototype.resetFocusState = function() {
+ uiLogger.debug("Control.resetFocusState()");
+ this.hovering = false;
+ this.focused = false;
+ this.updateStyleFromState();
+}
+
+// Helper function that sets a classname for an element.
+// Only sets the class name if it actually is different from the current value.
+Control.prototype.setClassName = function(element, className) {
+ if (element.className != className) {
+ element.className = className;
+ }
+}
+
+// Updates the style of the control to reflects the state of the control.
+// Override this in subclasses as required to implement the state change.
+Control.prototype.updateStyleFromState = function() {
+ uiLogger.debug("Control.updateStyleFromState()");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/FormButton.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,177 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The FormButton class implements a button control for use in form-style UIs.
+
+// Constructor.
+function FormButton(id, text) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, text);
+ }
+}
+
+// FormButton inherits from ActionControl.
+FormButton.prototype = new ActionControl(UI_NO_INIT_ID);
+
+// Button table element.
+FormButton.prototype.tableElement = null;
+
+// Button table row element.
+FormButton.prototype.tableRowElement = null;
+
+// Button table left cell element.
+FormButton.prototype.tableLeftCellElement = null;
+
+// Button table center cell element.
+FormButton.prototype.tableCenterCellElement = null;
+
+// Button text element.
+FormButton.prototype.textElement = null;
+
+// Button table right cell element.
+FormButton.prototype.tableRightCellElement = null;
+
+// Initializer - called from constructor.
+FormButton.prototype.init = function(id, text) {
+ uiLogger.debug("FormButton.init(" + id + ", " + text + ")");
+
+ // call superclass initializer
+ ActionControl.prototype.init.call(this, id, null);
+
+ // remove caption element
+ this.assemblyElement.removeChild(this.captionElement);
+
+ // construct the button
+ this.buttonElement = document.createElement("div");
+ this.tableElement = document.createElement("table");
+ this.tableRowElement = document.createElement("tr");
+ this.tableLeftCellElement = document.createElement("td");
+ this.tableCenterCellElement = document.createElement("td");
+ this.linkElement = document.createElement("a");
+ this.linkElement.href = "JavaScript:void(0)";
+ this.textElement = document.createElement("span");
+ this.tableRightCellElement = document.createElement("td");
+ this.tableElement.appendChild(this.tableRowElement);
+ this.tableRowElement.appendChild(this.tableLeftCellElement);
+ this.tableRowElement.appendChild(this.tableCenterCellElement);
+ this.tableCenterCellElement.appendChild(this.linkElement);
+ this.linkElement.appendChild(this.textElement);
+ this.tableRowElement.appendChild(this.tableRightCellElement);
+ this.buttonElement.appendChild(this.tableElement);
+ this.controlElement.appendChild(this.buttonElement);
+
+ // set the text
+ this.setText(text);
+
+ // bind event listeners
+ this.bindActionControlListeners();
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Sets the enabled state.
+FormButton.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("FormButton.setEnabled(" + enabled + ")");
+
+ // bail out early if there is no change in state
+ if (this.enabled == enabled) {
+ return;
+ }
+
+ // set the enabled state
+ this.enabled = enabled;
+
+ if (this.enabled) {
+ // diabled -> enabled
+ this.tableCenterCellElement.removeChild(this.textElement);
+ this.tableCenterCellElement.appendChild(this.linkElement);
+ this.linkElement.appendChild(this.textElement);
+ } else {
+ // enabled -> diabled
+ this.linkElement.removeChild(this.textElement);
+ this.tableCenterCellElement.removeChild(this.linkElement);
+ this.tableCenterCellElement.appendChild(this.textElement);
+ }
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Returns the button text.
+FormButton.prototype.getText = function() {
+ return this.textElement.innerHTML;
+}
+
+// Sets the button text.
+FormButton.prototype.setText = function(text) {
+ uiLogger.debug("FormButton.setText(" + text + ")");
+ this.textElement.innerHTML = (text == null) ? "" : text;;
+}
+
+// Updates the style of the control to reflects the state of the control.
+FormButton.prototype.updateStyleFromState = function() {
+ uiLogger.debug("FormButton.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set root element class name
+ this.setClassName(this.rootElement, "Control");
+
+ // set the control assembly class names
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssemblyNormal");
+
+ // control element
+ this.setClassName(this.controlElement, "ControlElement FormButtonControlElement");
+
+ // set the button table class names
+ this.setClassName(this.buttonElement, "FormButton");
+ this.setClassName(this.tableElement, "FormButtonTable");
+ this.setClassName(this.tableRowElement, "FormButtonRow");
+ this.setClassName(this.tableLeftCellElement, "FormButtonLeftCell FormButtonLeftCell" + stateName);
+ this.setClassName(this.tableCenterCellElement, "FormButtonCenterCell FormButtonLeftCell" + stateName);
+ this.setClassName(this.tableRightCellElement, "FormButtonRightCell FormButtonLeftCell" + stateName);
+
+ // set the button text class name
+ this.setClassName(this.textElement, "FormButtonText FormButtonText" + stateName);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/ImageLabel.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,69 @@
+///////////////////////////////////////////////////////////////////////////////
+// The ImageLabel class implements a control that displays an image
+
+// Constructor.
+function ImageLabel(id, caption, image) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, image);
+ }
+}
+
+// Label inherits from Control.
+ImageLabel.prototype = new Control(UI_NO_INIT_ID);
+
+// Content element for label text.
+ImageLabel.prototype.contentElement = null;
+
+// Content element for label text.
+ImageLabel.prototype.image = null;
+
+// Initializer - called from constructor.
+ImageLabel.prototype.init = function(id, caption, image) {
+ uiLogger.debug("ImageLabel.init(" + id + ", " + caption + ", " + image + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, caption);
+
+ this.image = image;
+
+ // create content element
+ this.contentElement = document.createElement("div");
+ this.controlElement.appendChild(this.contentElement);
+
+ // set the image
+ this.setImage(image);
+}
+
+// Returns the enabled state for the control.
+ImageLabel.prototype.isEnabled = function() {
+ return true;
+}
+
+// Returns the focusable state for the control.
+ImageLabel.prototype.isFocusable = function() {
+ return false;
+}
+
+// Returns the control text.
+ImageLabel.prototype.getImage = function() {
+ return this.contentElement.innerHTML;
+}
+
+// Sets the text for the control.
+ImageLabel.prototype.setText = function(text) {
+ uiLogger.debug("Label.setText(" + text + ")");
+ this.contentElement.innerHTML = (text == null) ? "" : text;
+ this.updateStyleFromState();
+}
+
+// Updates the style of the control to reflects the state of the control.
+ImageLabel.prototype.updateStyleFromState = function() {
+ uiLogger.debug("Label.updateStyleFromState()");
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssemblyNormal");
+ this.setClassName(this.captionElement, "ControlCaption ControlCaptionNormal");
+ this.setClassName(this.controlElement, "ControlElement");
+ this.setClassName(this.contentElement, "LabelText");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/Label.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,105 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The Label class implements a control that displays textual content.
+
+// Constructor.
+function Label(id, caption, text) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, text);
+ }
+}
+
+// Label inherits from Control.
+Label.prototype = new Control(UI_NO_INIT_ID);
+
+// Content element for label text.
+Label.prototype.contentElement = null;
+
+// Initializer - called from constructor.
+Label.prototype.init = function(id, caption, text) {
+ uiLogger.debug("Label.init(" + id + ", " + caption + ", " + text + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, caption);
+
+ // create content element
+ this.contentElement = document.createElement("div");
+ this.controlElement.appendChild(this.contentElement);
+
+ // set the text
+ this.setText(text);
+}
+
+// Returns the enabled state for the control.
+Label.prototype.isEnabled = function() {
+ return true;
+}
+
+// Returns the focusable state for the control.
+Label.prototype.isFocusable = function() {
+ return false;
+}
+
+// Returns the control text.
+Label.prototype.getText = function() {
+ return this.contentElement.innerHTML;
+}
+
+// Sets the text for the control.
+Label.prototype.setText = function(text) {
+ uiLogger.debug("Label.setText(" + text + ")");
+ this.contentElement.innerHTML = (text == null) ? "" : text;
+ this.updateStyleFromState();
+}
+
+// Updates the style of the control to reflects the state of the control.
+Label.prototype.updateStyleFromState = function() {
+ uiLogger.debug("Label.updateStyleFromState()");
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssemblyNormal");
+ this.setClassName(this.captionElement, "ControlCaption ControlCaptionNormal");
+ this.setClassName(this.controlElement, "ControlElement");
+ this.setClassName(this.contentElement, "LabelText");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/ListView.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,186 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The ListView class implements a vertical list view that hosts controls
+// as child components.
+
+// Constructor.
+function ListView(id, caption) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption);
+ }
+}
+
+// ListView inherits from View.
+ListView.prototype = new View(UI_NO_INIT_ID);
+
+// The caption of this view; null if none.
+ListView.prototype.caption = null;
+
+// The caption element of this view.
+ListView.prototype.captionElement = null;
+
+// The caption text element of this view.
+ListView.prototype.captionTextElement = null;
+
+// Root HTML element for controls.
+ListView.prototype.listElement = null;
+
+// List of controls in the view.
+ListView.prototype.controls = null;
+
+// Initializer for ListView.
+ListView.prototype.init = function(id, caption) {
+ uiLogger.debug("ListView.init(" + id + ", " + caption + ")");
+
+ // call superclass initializer
+ View.prototype.init.call(this, id);
+
+ // init control array
+ this.controls = [];
+
+ // set style class name for root element
+ this.rootElement.className = "ListView";
+
+ // create caption and caption text elements
+ this.captionElement = document.createElement("div");
+ this.captionElement.className = "ListViewCaptionText";
+ this.rootElement.appendChild(this.captionElement);
+
+ // create root element for controls and add to the view root element
+ this.listElement = document.createElement("div");
+ this.listElement.className = "ListViewControlList";
+ this.rootElement.appendChild(this.listElement);
+
+ // set the caption
+ this.setCaption(caption);
+}
+
+// Returns the caption; null if none.
+ListView.prototype.getCaption = function() {
+ return this.caption;
+}
+
+// Sets the caption; null if none.
+ListView.prototype.setCaption = function(caption) {
+ uiLogger.debug("ListView.setCaption(" + caption + ")");
+
+ // set the display style
+ this.captionElement.style.display = (caption == null) ? "none" : "block";
+
+ // set the caption
+ this.caption = caption;
+ this.captionElement.innerHTML = (caption == null) ? "" : caption;
+}
+
+// Returns an array of controls in the view.
+ListView.prototype.getControls = function() {
+ return this.controls;
+}
+
+// Adds a control to the view.
+ListView.prototype.addControl = function(control) {
+ uiLogger.debug("ListView.addControl(" + control + ")");
+
+ // add the control to the controls array and attach it to the list element
+ this.controls.push(control);
+ this.listElement.appendChild(control.rootElement);
+ control.view = this;
+}
+
+// Inserts a control to the view before the specified control.
+ListView.prototype.insertControl = function(control, beforeControl) {
+ uiLogger.debug("ListView.insertControl(" + control + ", " + beforeControl + ")");
+
+ // iterate through current controls
+ for (var i = 0; i < this.controls.length; i++) {
+ // is this the control we should insert before?
+ if (this.controls[i] == beforeControl) {
+ // we found the control to insert before - insert here and connect to list element
+ this.controls.splice(i, 0, control);
+ this.listElement.insertBefore(control.rootElement, beforeControl.rootElement);
+ control.view = this;
+ return;
+ }
+ }
+
+ // the control wasn't found so we'll add it last
+ this.addControl(control);
+}
+
+// Removes a control from the view.
+ListView.prototype.removeControl = function(control) {
+ uiLogger.debug("ListView.removeControl(" + control + ")");
+
+ // iterate through current controls
+ for (var i = 0; i < this.controls.length; i++) {
+ // is this the control we should remove?
+ if (this.controls[i] == control) {
+ // we found the control to remove - remove it from the list element
+ this.controls.splice(i, 1);
+ this.listElement.removeChild(control.rootElement);
+ control.view = null;
+ }
+ }
+}
+
+// Attempts to focus the first focusable control.
+ListView.prototype.focusFirstControl = function() {
+ uiLogger.debug("ListView.focusFirstControl()");
+ for (var i = 0; i < this.controls.length; i++) {
+ // is this control focusable?
+ var control = this.controls[i];
+ if (control.isFocusable()) {
+ control.setFocused(true);
+ break;
+ }
+ }
+}
+
+// Attempts to reset all control focus states.
+// Override in subclasses as required.
+ListView.prototype.resetControlFocusStates = function() {
+ uiLogger.debug("ListView.resetControlFocusStates()");
+ for (var i = 0; i < this.controls.length; i++) {
+ this.controls[i].resetFocusState();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/NavigationButton.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,220 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The NavigationButton class implements a button control for use in
+// navigational contexts in menu-style UIs.
+
+// Constructor.
+function NavigationButton(id, image, text) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, image, text);
+ }
+}
+
+// NavigationButton inherits from ActionControl.
+NavigationButton.prototype = new ActionControl(UI_NO_INIT_ID);
+
+// Button table element.
+NavigationButton.prototype.tableElement = null;
+
+// Button table row element.
+NavigationButton.prototype.tableRowElement = null;
+
+// Button table left cell element.
+NavigationButton.prototype.tableLeftCellElement = null;
+
+// Button table right cell element.
+NavigationButton.prototype.tableRightCellElement = null;
+
+// Button image element.
+NavigationButton.prototype.imageElement = null;
+
+// Button link element.
+NavigationButton.prototype.linkElement = null;
+
+// Button text element.
+NavigationButton.prototype.textElement = null;
+
+// Initializer - called from constructor.
+NavigationButton.prototype.init = function(id, image, text) {
+ uiLogger.debug("NavigationButton.init(" + id + ", " + image + ", " + text + ")");
+
+ // call superclass initializer
+ ActionControl.prototype.init.call(this, id, null);
+
+ // remove caption element
+ this.assemblyElement.removeChild(this.captionElement);
+
+ // construct the button
+ this.buttonElement = document.createElement("div");
+ this.tableElement = document.createElement("table");
+ this.tableRowElement = document.createElement("tr");
+ this.tableLeftCellElement = document.createElement("td");
+ this.tableRightCellElement = document.createElement("td");
+ this.imageElement = null;
+ this.linkElement = document.createElement("a");
+ this.linkElement.href = "JavaScript:void(0)";
+ this.textElement = document.createElement("span");
+ this.tableElement.appendChild(this.tableRowElement);
+ this.tableRowElement.appendChild(this.tableLeftCellElement);
+ this.tableRowElement.appendChild(this.tableRightCellElement);
+ this.tableRightCellElement.appendChild(this.linkElement);
+ this.linkElement.appendChild(this.textElement);
+ this.buttonElement.appendChild(this.tableElement);
+ this.controlElement.appendChild(this.buttonElement);
+
+ // set the image and text
+ this.setImage(image);
+ this.setText(text);
+
+ // bind event listeners
+ this.bindActionControlListeners();
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Sets the enabled state.
+NavigationButton.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("NavigationButton.setEnabled(" + enabled + ")");
+
+ // bail out early if there is no change in state
+ if (this.enabled == enabled) {
+ return;
+ }
+
+ // set the enabled state
+ this.enabled = enabled;
+
+ if (this.enabled) {
+ // diabled -> enabled
+ this.tableRightCellElement.removeChild(this.textElement);
+ this.tableRightCellElement.appendChild(this.linkElement);
+ this.linkElement.appendChild(this.textElement);
+ } else {
+ // enabled -> diabled
+ this.linkElement.removeChild(this.textElement);
+ this.tableRightCellElement.removeChild(this.linkElement);
+ this.tableRightCellElement.appendChild(this.textElement);
+ }
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Returns the button image (URL); null if none.
+NavigationButton.prototype.getImage = function() {
+ return (this.imageElement != null) ? this.imageElement.src : null;
+}
+
+// Sets the button image (URL); null if none.
+NavigationButton.prototype.setImage = function(image) {
+ uiLogger.debug("NavigationButton.setImage(" + image + ")");
+
+ if (image == null) {
+ // remove image - if any
+ if (this.imageElement != null) {
+ this.tableLeftCellElement.removeChild(this.imageElement);
+ }
+ } else {
+ // default to not append image element
+ var append = false;
+
+ // create image element if one doesn't exist
+ if (this.imageElement == null) {
+ this.imageElement = document.createElement("img");
+ this.imageElement.setAttribute("alt", "");
+ append = true;
+ }
+
+ // set image source URL
+ this.imageElement.src = image;
+
+ // append the image element to the left cell?
+ if (append) {
+ this.tableLeftCellElement.appendChild(this.imageElement);
+ }
+ }
+}
+
+// Returns the button text.
+NavigationButton.prototype.getText = function() {
+ return this.textElement.innerHTML;
+}
+
+// Sets the button text.
+NavigationButton.prototype.setText = function(text) {
+ uiLogger.debug("NavigationButton.setText(" + text + ")");
+ this.textElement.innerHTML = (text == null) ? "" : text;;
+}
+
+// Updates the style of the control to reflects the state of the control.
+NavigationButton.prototype.updateStyleFromState = function() {
+ uiLogger.debug("NavigationButton.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set root element class name
+ this.setClassName(this.rootElement, "Control");
+
+ // set the control assembly class names
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
+
+ // control element
+ this.setClassName(this.controlElement, "ControlElement NavigationButtonControlElement");
+
+ // set the button table class names
+ this.setClassName(this.buttonElement, "NavigationButton");
+ this.setClassName(this.tableElement, "NavigationButtonTable");
+ this.setClassName(this.tableRowElement, "NavigationButtonRow");
+ this.setClassName(this.tableLeftCellElement, "NavigationButtonImageCell");
+ this.setClassName(this.tableRightCellElement, "NavigationButtonTextCell");
+
+ // set image class names
+ if (this.imageElement) {
+ this.setClassName(this.imageElement, "NavigationButtonImage");
+ }
+
+ // set the button text class name
+ this.setClassName(this.textElement, "NavigationButtonText NavigationButtonText" + stateName);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/NotificationPopup.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,321 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The NotificationPopup class handles the display of notifications such as
+// warnings, information messages and progress indication.
+
+// Constructor.
+function NotificationPopup() {
+ // create notification popup
+ this.containerElement = document.createElement("div");
+ this.containerElement.className = "NotificationPopupContainer";
+ this.popupElement = document.createElement("div");
+ this.popupElement.className = "NotificationPopup";
+ this.typeIndicatorElement = document.createElement("div");
+ this.typeIndicatorElement.className = "NotificationPopupTypeIndicator";
+ this.textElement = document.createElement("div");
+ this.textElement.className = "NotificationPopupText";
+ this.progressBarElement = document.createElement("div");
+ this.progressBarElement.className = "NotificationPopupProgressBar";
+
+ // assemble popup
+ this.popupElement.appendChild(this.typeIndicatorElement);
+ this.popupElement.appendChild(this.textElement);
+ this.popupElement.appendChild(this.progressBarElement);
+ this.containerElement.appendChild(this.popupElement);
+
+ // create progress bar image element and initialize it
+ this.progressBarImageElement = document.createElement("img");
+ var self = this;
+ this.progressBarImageElement.addEventListener("load", function() { self.progressBarImageLoadingCompleted(); }, false);
+ this.progressBarImageElement.setAttribute("alt", "");
+ this.progressBarImageURL = this.getProgressBarImage(this.PROGRESS_BAR_IMAGE_NONE);
+ this.progressBarImageElement.src = this.progressBarImageURL;
+ this.progressBarElement.appendChild(this.progressBarImageElement);
+
+ // init the popup to be fully down
+ this.popupElement.style.top = "100%";
+
+ // set default popup contents
+ this.setPopupContents(null, null, null);
+}
+
+// Notification container element.
+NotificationPopup.prototype.containerElement = null;
+
+// Notification popup element.
+NotificationPopup.prototype.popupElement = null;
+
+// Type indicator element.
+NotificationPopup.prototype.typeIndicatorElement = null;
+
+// Notification text element.
+NotificationPopup.prototype.textElement = null;
+
+// Progress bar element.
+NotificationPopup.prototype.progressBarElement = null;
+
+// Progress bar image element.
+NotificationPopup.prototype.progressBarImageElement = null;
+
+// Progress bar image URL.
+NotificationPopup.prototype.progressBarImageURL = null;
+
+// Has the progress bar image been loaded?
+NotificationPopup.prototype.progressBarImageLoaded = false;
+
+// Flag that tracks whether we're in the middle of starting to
+// show a notification popup.
+NotificationPopup.prototype.processingShowNotification = false;
+
+// Notification popup position (0 = hidden, 1 = showing).
+NotificationPopup.prototype.popupPosition = 0;
+
+// Interval for timer ticks (in milliseconds)
+NotificationPopup.prototype.ANIM_TIMER_INTERVAL = 25;
+
+// Animation timer identifier or null if no active timer.
+NotificationPopup.prototype.animTimerId = null;
+
+// Time in milliseconds for the popup animation to complete
+NotificationPopup.prototype.ANIM_TIME = 300;
+
+// Flag that determines the behavior of showNotification(). If set to true
+// the popup will snap open when showNotification() is called instead of
+// animation.
+NotificationPopup.prototype.SHOW_SNAPS_OPEN = true;
+
+// Animation direction (0 = no movement, -1 hiding, +1 = showing).
+NotificationPopup.prototype.animDir = 0;
+
+// Auto-hide timer identifier or null if no active timer.
+NotificationPopup.prototype.autoHideTimerId = null;
+
+// The commanded display time.
+NotificationPopup.prototype.displayTime = -1;
+
+NotificationPopup.prototype.PROGRESS_BAR_IMAGE_NONE = 0;
+
+// Displays a notification.
+NotificationPopup.prototype.showNotification = function(displayTime, type, text, progress) {
+ uiLogger.debug("NotificationPopup.showNotification(" + displayTime + ", " + type + ", " + text + ", " + progress + ")");
+
+ // mark that showNotification() has been called and that we are in
+ // the middle of starting to show the notification popup
+ this.processingShowNotification = true;
+
+ // remember the display time
+ this.displayTime = displayTime;
+
+ // attach the popup to the document if not attached
+ if (this.containerElement.parentNode == null) {
+ document.body.appendChild(this.containerElement);
+ uiLogger.debug("Notification popup attached to document");
+ }
+
+ // set popup contents and update style
+ this.setPopupContents(type, text, progress);
+
+ // if the progress image is loaded then we can complete the showing
+ // of the notification popup immediately - otherwise the image loaded
+ // allback will complete the process.
+ if (this.progressBarImageLoaded) {
+ this.completeShowNotification();
+ }
+}
+
+// Completes displaying of a notification.
+// Note: Used internally - don't call this directly.
+NotificationPopup.prototype.completeShowNotification = function() {
+ uiLogger.debug("NotificationPopup.completeShowNotification()");
+
+ // animation direction is +1 for showing the popup
+ if (this.popupPosition != 1) {
+ if (this.SHOW_SNAPS_OPEN) {
+ if (this.popupPosition == 0) {
+ this.popupPosition = 1;
+ }
+ }
+ this.animatePopup(1);
+ }
+
+ // setup auto hiding if a display time is specified
+ if (this.displayTime > 0) {
+ // stop any existing timer
+ if (this.autoHideTimerId != null) {
+ clearTimeout(this.autoHideTimerId);
+ uiLogger.debug("Auto hide timer stopped");
+ }
+ // set timer to hide notification
+ var self = this;
+ this.autoHideTimerId = setTimeout(function() {
+ if (self.displayTime > 0) {
+ self.hideNotification();
+ }
+ }, this.ANIM_TIME + this.displayTime);
+ uiLogger.debug("Auto hide timer started");
+ }
+
+ // mark us as no longer processing a show notification call
+ this.processingShowNotification = false;
+}
+
+// Hides the currently displayed notification.
+NotificationPopup.prototype.hideNotification = function() {
+ uiLogger.debug("NotificationPopup.hideNotification()");
+ // mark us as no longer processing a show notification call
+ this.processingShowNotification = false;
+
+ // animation direction is -1 for hiding the popup
+ if (this.popupPosition != 0) {
+ this.animatePopup(-1);
+ }
+
+ // stop auto hide timer if one is set
+ if (this.autoHideTimerId != null) {
+ clearTimeout(this.autoHideTimerId);
+ this.autoHideTimerId = null;
+ uiLogger.debug("Auto hide timer stopped");
+ }
+}
+
+// Starts animation of the popup (1 to show, -1 to hide).
+NotificationPopup.prototype.animatePopup = function(direction) {
+ uiLogger.debug("NotificationPopup.animatePopup(" + direction + ")");
+ // set the direction and star the animation timer
+ this.animDir = direction;
+ if (this.animTimerId == null) {
+ var self = this;
+ this.animTimerId = setInterval(function() { self.animate(); }, this.ANIM_TIMER_INTERVAL);
+ uiLogger.debug("Notification popup animation started");
+ }
+}
+
+// Callback for animation timer.
+NotificationPopup.prototype.animate = function() {
+ // calculate new popup position and clamp
+ var animStep = (this.ANIM_TIMER_INTERVAL / this.ANIM_TIME) * this.animDir;
+ var newPos = this.popupPosition + animStep;
+ if (newPos < 0) {
+ newPos = 0;
+ } else if (newPos > 1) {
+ newPos = 1;
+ }
+
+ // set the new position to the popup element
+ this.popupPosition = newPos;
+ this.popupElement.style.top = (100 - Math.round(this.popupPosition * 100)) + "%";
+
+ // have we reached the end of the animation?
+ if (newPos == 0 || newPos == 1) {
+ // reset animation direction
+ this.animDir = 0;
+
+ // remove the popup from the body if its hidden
+ if (newPos == 0) {
+ document.body.removeChild(this.containerElement);
+ uiLogger.debug("Notification popup detached from document");
+ }
+
+ // stop timer
+ clearTimeout(this.animTimerId);
+ this.animTimerId = null;
+ uiLogger.debug("Notification popup animation stopped");
+ }
+}
+
+// Returns a URL for the progress bar image to use for the specified progress.
+NotificationPopup.prototype.getProgressBarImage = function(progress) {
+ // path for progress bar images
+ var progressBarImagePath = "WRTKit/Resources/";
+
+ // unknown progress
+ return progressBarImagePath + "ProgressBarUnknown.gif";
+}
+
+// Sets the contents of the popup.
+NotificationPopup.prototype.setPopupContents = function(type, text, progress) {
+ uiLogger.debug("NotificationPopup.setPopupContents(" + type + ", " + text + ", " + progress + ")");
+
+ // figure out notification type style name
+ var typeName = (type == null) ? "none" : type.toLowerCase();
+ typeName = typeName.charAt(0).toUpperCase() + typeName.substring(1);
+
+ // set type element class names
+ this.typeIndicatorElement.className = "NotificationPopupTypeIndicator NotificationPopupTypeIndicator" + typeName;
+
+ // set notification text
+ this.textElement.innerHTML = (text == null) ? "" : text;
+
+ // set progress
+ this.progressBarElement.style.display = (progress == null) ? "none" : "block";
+ if (progress != null) {
+ var imgURL = this.getProgressBarImage(progress);
+ if (imgURL != this.progressBarImageURL) {
+ // load new image
+ this.progressBarImageLoaded = false;
+ this.progressBarImageURL = imgURL;
+ this.progressBarImageElement.src = imgURL;
+ } else {
+ // the correct image is already loaded
+ this.progressBarImageLoaded = true;
+ }
+ } else {
+ // there is no progress bar so there is no need
+ // to load any progress bar image
+ this.progressBarImageLoaded = true;
+ }
+}
+
+// Callback for notifying the object that its progress bar image completed loading.
+NotificationPopup.prototype.progressBarImageLoadingCompleted = function() {
+ uiLogger.debug("NotificationPopup.progressBarImageLoadingCompleted()");
+
+ // mark the progress bar image as loaded
+ this.progressBarImageLoaded = true;
+
+ // complete the process of displaying the notification popup
+ // if it has been commanded but not yet completed
+ if (this.processingShowNotification) {
+ this.completeShowNotification();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/Scrollbar.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,173 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The Scrollbar class is an implementation of a user interface element that
+// indicates the current viewport position in a document.
+
+// Constructor.
+function Scrollbar(parentElement) {
+ uiLogger.debug("Scrollbar(" + parentElement + ")");
+
+ // get the parent element
+ this.parentElement = parentElement;
+
+ // create the root element
+ this.rootElement = document.createElement("div");
+ this.rootElement.className = "Scrollbar";
+ this.rootElement.style.visibility = "hidden";
+
+ // create the scrollbar
+ // the scrollbar consists of a root element with six children
+ // (three track elements and three thumb elements)
+
+ // track
+ this.trackTopElement = document.createElement("div");
+ this.trackTopElement.className = "ScrollbarTrackTop";
+ this.trackMiddleElement = document.createElement("div");
+ this.trackMiddleElement.className = "ScrollbarTrackMiddle";
+ this.trackBottomElement = document.createElement("div");
+ this.trackBottomElement.className = "ScrollbarTrackBottom";
+
+ // thumb
+ this.thumbTopElement = document.createElement("div");
+ this.thumbTopElement.className = "ScrollbarThumbTop";
+ this.thumbMiddleElement = document.createElement("div");
+ this.thumbMiddleElement.className = "ScrollbarThumbMiddle";
+ this.thumbBottomElement = document.createElement("div");
+ this.thumbBottomElement.className = "ScrollbarThumbBottom";
+
+ // assemble and attach the scrollbar
+ this.rootElement.appendChild(this.trackTopElement);
+ this.rootElement.appendChild(this.trackMiddleElement);
+ this.rootElement.appendChild(this.trackBottomElement);
+ this.rootElement.appendChild(this.thumbTopElement);
+ this.rootElement.appendChild(this.thumbMiddleElement);
+ this.rootElement.appendChild(this.thumbBottomElement);
+ this.parentElement.appendChild(this.rootElement);
+
+ // bring the scrollbar up to date
+ this.update(0, 100, 100);
+}
+
+// Parent element for the scrollbar.
+Scrollbar.prototype.parentElement = null;
+
+// Root HTML element in the scrollbar.
+Scrollbar.prototype.rootElement = null;
+
+// Scrollbar track top element.
+Scrollbar.prototype.trackTopElement = null;
+
+// Scrollbar track middle element.
+Scrollbar.prototype.trackMiddleElement = null;
+
+// Scrollbar track bottom element.
+Scrollbar.prototype.trackBottomElement = null;
+
+// Scrollbar thumb top element.
+Scrollbar.prototype.thumbTopElement = null;
+
+// Scrollbar thumb middle element.
+Scrollbar.prototype.thumbMiddleElement = null;
+
+// Scrollbar thumb bottom element.
+Scrollbar.prototype.thumbBottomElement = null;
+
+// Is the scrollbar needed?
+Scrollbar.prototype.scrollbarNeeded = false;
+
+// Updates the scrollbar.
+Scrollbar.prototype.update = function(scrollY, viewportHeight, documentHeight) {
+ // figure out current heights
+ var scrollbarHeight = this.rootElement.clientHeight;
+ var trackTopHeight = this.trackTopElement.clientHeight;
+ var trackBottomHeight = this.trackBottomElement.clientHeight;
+ var thumbTopHeight = this.thumbTopElement.clientHeight;
+ var thumbBottomHeight = this.thumbBottomElement.clientHeight;
+
+ // scrollable height is the larger of document and viewport heights
+ var scrollableHeight = documentHeight;
+ var scrollbarNeeded = true;
+ if (viewportHeight >= documentHeight) {
+ scrollableHeight = viewportHeight;
+ scrollbarNeeded = false;
+ }
+
+ // show or hide scrollbar?
+ if (scrollbarNeeded != this.scrollbarNeeded) {
+ this.scrollbarNeeded = scrollbarNeeded;
+ this.rootElement.style.visibility = scrollbarNeeded ? "visible" : "hidden";
+ }
+
+ // calculate thumb top position...
+ var thumbTopPct = scrollY / scrollableHeight;
+ var thumbTop = scrollbarHeight * thumbTopPct;
+ // ...and bottom position...
+ var thumbBottomPct = (scrollY + viewportHeight) / scrollableHeight;
+ var thumbBottom = scrollbarHeight * thumbBottomPct;
+
+ // ...and thumb height
+ var thumbHeight = thumbBottom - thumbTop;
+
+ // ensure that the thumb is not too small
+ var thumbMinHeight = thumbTopHeight + thumbBottomHeight;
+ if (thumbHeight < thumbMinHeight) {
+ var underflow = thumbMinHeight - thumbHeight;
+ // adjust thumb top pos assuming a shorter scrollbar track
+ var thumbMid = (scrollbarHeight - underflow) * ((thumbTopPct + thumbBottomPct) / 2) + (underflow / 2);
+ thumbTop = thumbMid - (thumbMinHeight / 2);
+ thumbBottom = thumbTop + thumbMinHeight;
+ thumbHeight = thumbBottom - thumbTop;
+ }
+
+ // position and size track element (add 1 to the middle section height for rounding errors)
+ this.trackTopElement.style.top = "0px";
+ this.trackMiddleElement.style.top = Math.round(trackTopHeight) + "px";
+ this.trackMiddleElement.style.height = Math.round(scrollbarHeight - trackTopHeight - trackBottomHeight + 1) + "px";
+ this.trackBottomElement.style.top = Math.round(scrollbarHeight - trackTopHeight) + "px";
+
+ // position and size thumb element (add 1 to the middle section height for rounding errors)
+ this.thumbTopElement.style.top = Math.round(thumbTop) + "px";
+ this.thumbMiddleElement.style.top = Math.round(thumbTop + thumbTopHeight) + "px";
+ this.thumbMiddleElement.style.height = Math.round(thumbHeight - thumbTopHeight - thumbBottomHeight + 1) + "px";
+ this.thumbBottomElement.style.top = Math.round(thumbBottom - thumbBottomHeight) + "px";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/SelectionControl.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,189 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The SelectionControl class is an abstract base class for controls that lets
+// the user select one or more options from a list of options. Don't use
+// SelectionControl directly.
+
+// Constructor.
+function SelectionControl(id, caption, options, multipleSelection, selected) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, options, multipleSelection, selected);
+ }
+}
+
+// SelectionControl inherits from Control.
+SelectionControl.prototype = new Control(UI_NO_INIT_ID);
+
+// List of options.
+SelectionControl.prototype.options = null;
+
+// The single selected option in single selection controls
+// or list of options in multi selection controls.
+SelectionControl.prototype.selected = null;
+
+// Single or multiple selection.
+SelectionControl.prototype.multipleSelection = false;
+
+// Initializer - called from constructor.
+SelectionControl.prototype.init = function(id, caption, options, multipleSelection, selected) {
+ uiLogger.debug("SelectionControl.init(" + id + ", " + caption + ", " + options + ", " + multipleSelection + ", " + selected + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, caption);
+
+ // set the multiple selection property
+ this.multipleSelection = multipleSelection;
+
+ // init options and selected (makes copies of the original arrays)
+ this.options = (options != null) ? options.slice(0) : [];
+ if (multipleSelection) {
+ this.selected = (selected == null) ? [] : selected.slice(0);
+ } else {
+ this.selected = selected;
+ }
+ this.validateSelected();
+}
+
+// Returns true if the control is a multiple selection control; false if single.
+SelectionControl.prototype.isMultipleSelection = function() {
+ return this.multipleSelection;
+}
+
+// Returns true if the specified option is selected; false if not.
+SelectionControl.prototype.isSelected = function(option) {
+ if (this.multipleSelection) {
+ // multiple selection
+ // iterate through all selected options and look for the specified option
+ for (var i = 0; i < this.selected.length; i++) {
+ if (this.selected[i] == option) {
+ return true;
+ }
+ }
+ return false;
+ } else {
+ // single selection
+ return (this.selected == option);
+ }
+}
+
+// Returns the currently selected option in a single selection control or
+// an array of selected options in a multiple selection control. If there are
+// no selected options a single selection control returns null and a multiple
+// selection control returns an empty array.
+SelectionControl.prototype.getSelected = function() {
+ return this.multipleSelection ? this.selected.slice(0) : this.selected;
+}
+
+// Sets the currently selected options. Pass a single option in a single selection
+// control or an array of selected controls in a multiple selection control. To
+// deselect all options pass null in a single selection control and an empty array
+// in a multiple selection control.
+// Override in sublcasses to provide full implementation.
+SelectionControl.prototype.setSelected = function(selected) {
+ this.selected = this.multipleSelection ? selected.slice(0) : selected;
+ // make sure the selected option or options are legal
+ this.validateSelected();
+}
+
+// Ensures that the selected option or options exist among the options in this control.
+SelectionControl.prototype.validateSelected = function() {
+ if (this.multipleSelection) {
+ // multiple selection
+ // iterate through all selected options and ensure they exist among the options
+ for (var i = 0; i < this.selected.length; i++) {
+ // check that the selected option exists among the options
+ var found = false;
+ for (var j = 0; j < this.options.length; j++) {
+ if (this.options[j] == this.selected[i]) {
+ // found - stop looking for this option
+ found = true;
+ break;
+ }
+ }
+ // not found - remove this selected element
+ if (!found) {
+ this.selected.splice(i, 1);
+ // since we removed an entry we must re-check this position
+ i--;
+ }
+ }
+ } else {
+ // single selection
+ if (this.selected != null) {
+ // check that the selected option exists among the options
+ for (var i = 0; i < this.options.length; i++) {
+ if (this.options[i] == this.selected) {
+ // found - we're done
+ return;
+ }
+ }
+ // not found - remove the selection
+ this.selected = null;
+ }
+ }
+}
+
+// Returns the options in the control as an array of option objects with
+// a value and text property.
+SelectionControl.prototype.getOptions = function() {
+ return this.options;
+}
+
+// Sets the options in the control.
+// Override in sublcasses to provide full implementation.
+SelectionControl.prototype.setOptions = function(options) {
+ this.options = options.slice(0);
+ // make sure the selected option or options are legal
+ this.validateSelected();
+}
+
+// Returns the option that has the specified value; null if none.
+SelectionControl.prototype.getOptionForValue = function(value) {
+ // iterate through all options and look for a match
+ for (var i = 0; i < this.options.length; i++) {
+ if (this.options[i].value == value) {
+ return this.options[i];
+ }
+ }
+ return null;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/SelectionList.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,355 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The SelectionList class implements a single or multi selection control
+// that lets users select one or more options from a list of options.
+
+// Constructor.
+function SelectionList(id, caption, options, multipleSelection, selected) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, options, multipleSelection, selected);
+ }
+}
+
+// SelectionList inherits from SelectionControl.
+SelectionList.prototype = new SelectionControl(UI_NO_INIT_ID);
+
+// Root element for options.
+SelectionList.prototype.optionListElement = null;
+
+// Array for tracking option elements.
+SelectionList.prototype.optionElements = null;
+
+// Tracking for currently focused option; null if none.
+SelectionList.prototype.focusedOption = null;
+
+// Enabled status.
+SelectionList.prototype.enabled = false;
+
+// Initializer - called from constructor.
+SelectionList.prototype.init = function(id, caption, options, multipleSelection, selected) {
+ uiLogger.debug("SelectionList.init(" + id + ", " + caption + ", " + options + ", " + multipleSelection + ", " + selected + ")");
+
+ // call superclass initializer
+ SelectionControl.prototype.init.call(this, id, caption, options, multipleSelection, selected);
+
+ // create option list element
+ this.optionListElement = document.createElement("div");
+ this.controlElement.appendChild(this.optionListElement);
+
+ // the control defaults to enabled
+ this.enabled = true;
+
+ // init option element arrays
+ this.optionElements = [];
+
+ // update the option elements to match the options in this control
+ this.updateOptionElements();
+}
+
+// Returns the enabled state.
+SelectionList.prototype.isEnabled = function() {
+ return this.enabled;
+}
+
+// Sets the enabled state.
+SelectionList.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("SelectionList.setEnabled(" + enabled + ")");
+ // switch the state and update the the control
+ this.enabled = enabled;
+ this.updateOptionElements();
+}
+
+// Sets the focused state for the control.
+// Note: This may not always succeed.
+SelectionList.prototype.setFocused = function(focused) {
+ uiLogger.debug("SelectionList.setFocused(" + focused + ")");
+ if (this.enabled && this.optionElements.length > 0) {
+ if (focused) {
+ this.optionElements[0].link.focus();
+ } else {
+ this.optionElements[0].link.blur();
+ }
+ }
+}
+
+// Sets the currently selected options. Pass a single option in a single selection
+// control or an array of selected controls in a multiple selection control. To
+// deselect all options pass null in a single selection control and an empty array
+// in a multiple selection control.
+SelectionList.prototype.setSelected = function(selected) {
+ // call superclass setSelected()
+ SelectionControl.prototype.setSelected.call(this, selected);
+ this.updateStyleFromState();
+}
+
+// Sets the options in the control.
+SelectionList.prototype.setOptions = function(options) {
+ // call superclass setOptions()
+ SelectionControl.prototype.setOptions.call(this, options);
+ this.updateOptionElements();
+}
+
+// Updates the option elements for the control element.
+SelectionList.prototype.updateOptionElements = function() {
+ uiLogger.debug("SelectionControl.updateOptionElements()");
+
+ // start by removing all current options from the option list element
+ while (this.optionListElement.firstChild != null) {
+ this.optionListElement.removeChild(this.optionListElement.firstChild);
+ }
+
+ // iterate through the options and add (and possibly create) a
+ // properly configured option element for each option
+ for (var i = 0; i < this.options.length; i++) {
+ // get the option and option element we're working on
+ var option = this.options[i];
+
+ // option, link and text elements for this option
+ var optionElement;
+ var optionLinkElement;
+ var optionTextElement;
+
+ // get the elements
+ if (i == this.optionElements.length) {
+ // we need to create a new option element...
+ optionElement = document.createElement("div");
+
+ // ...and a new option link element...
+ optionLinkElement = document.createElement("a");
+ optionLinkElement.href = "JavaScript:void(0)";
+
+ // ...and a new option text element
+ optionTextElement = document.createElement("span");
+
+ // hook up event listeners to the element
+ var self = this;
+ optionLinkElement.addEventListener("focus", function(event) { self.optionFocusStateChanged(event, true); }, false);
+ optionLinkElement.addEventListener("blur", function(event) { self.optionFocusStateChanged(event, false); }, false);
+ optionElement.addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
+ optionElement.addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
+ optionElement.addEventListener("mousedown", function(event) {
+ self.optionClicked(event)
+ event.stopPropagation();
+ event.preventDefault();
+ }, true);
+ optionElement.addEventListener("keydown", function(event) {
+ // center and enter trigger the action
+ if (event.keyCode == 0 || event.keyCode == 13) {
+ self.optionClicked(event)
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }, true);
+
+ // add the elements to the option element array
+ this.optionElements.push({ option: optionElement, link: optionLinkElement, text: optionTextElement });
+ } else {
+ // we already have ready elements so we'll reuse them
+ optionElement = this.optionElements[i].option;
+ optionLinkElement = this.optionElements[i].link;
+ optionTextElement = this.optionElements[i].text;
+
+ // remove the option link element from its current parent - if any
+ if (optionLinkElement.parentNode != null) {
+ optionLinkElement.parentNode.removeChild(optionLinkElement);
+ }
+
+ // remove the option text element from its current parent - if any
+ if (optionTextElement.parentNode != null) {
+ optionTextElement.parentNode.removeChild(optionTextElement);
+ }
+ }
+
+ // set the option text
+ optionTextElement.innerHTML = option.text;
+
+ // hook up the option to the control
+ if (this.enabled) {
+ // add the option link element to the option element
+ optionElement.appendChild(optionLinkElement);
+ // add the text element to the option element
+ optionLinkElement.appendChild(optionTextElement);
+ } else {
+ // add the text element directly to the control element
+ optionElement.appendChild(optionTextElement);
+ }
+ // add the option element to the option list element
+ this.optionListElement.appendChild(optionElement);
+ }
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Callback for focus state change events.
+SelectionList.prototype.optionFocusStateChanged = function(event, focused) {
+ uiLogger.debug("SelectionControl.optionFocusStateChanged()");
+
+ // get the event source option
+ var option = null;
+ var optionElement = null;
+ for (var i = 0; i < this.optionElements.length; i++) {
+ optionElement = this.optionElements[i];
+ if (optionElement.link == event.currentTarget) {
+ option = this.options[i];
+ break;
+ }
+ }
+
+ // remember the focused option; or null if none is focused
+ if (focused) {
+ this.focusedOption = option;
+ } else {
+ this.focusedOption = null;
+ }
+
+ // call the superclass focus state change handler
+ this.focusStateChanged(focused);
+}
+
+// Callback for clicks.
+SelectionList.prototype.optionClicked = function(event) {
+ uiLogger.debug("SelectionControl.optionClicked()");
+
+ // bail out if we're not enabled
+ if (!this.enabled) {
+ return false;
+ }
+
+ // get the changed option
+ var option = null;
+ var optionElement = null;
+ for (var i = 0; i < this.optionElements.length; i++) {
+ optionElement = this.optionElements[i];
+ if (optionElement.option == event.currentTarget) {
+ option = this.options[i];
+ break;
+ }
+ }
+
+ // make sure the option is focused
+ optionElement.link.focus();
+
+ // toggle the selection
+ if (this.multipleSelection) {
+ // iterate through the selected options and see if this
+ // option is selected. if not then add it to the selection.
+ // if it already is selected then them remove it.
+ var found = false;
+ for (var i = 0; i < this.selected.length; i++) {
+ if (this.selected[i] == option) {
+ // remove from selected set
+ found = true;
+ this.selected.splice(i, 1);
+ break;
+ }
+ }
+ if (!found) {
+ // add to the selected set
+ this.selected.push(option);
+ }
+ } else {
+ // update the selected option
+ this.selected = option;
+ }
+
+ // update the style
+ this.updateStyleFromState();
+
+ // notify event listeners
+ this.fireEvent(this.createEvent("SelectionChanged", this.getSelected()));
+}
+
+// Resets the state tracking for focus and hover.
+// Override this in subclasses as required to implement the state reset.
+SelectionList.prototype.resetFocusState = function() {
+ uiLogger.debug("SelectionList.resetFocusState()");
+ this.hovering = false;
+ this.focused = false;
+ this.focusedOption = null;
+ this.updateStyleFromState();
+}
+
+// Updates the style of the control to reflects the state of the control.
+SelectionList.prototype.updateStyleFromState = function() {
+ uiLogger.debug("SelectionList.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.controlElement, "ControlElement");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
+ this.setClassName(this.captionElement, "ControlCaption ControlCaption" + stateName);
+
+ // set option list and option class names
+ this.setClassName(this.optionListElement, "SelectionList SelectionList" + stateName);
+ for (var i = 0; i < this.options.length; i++) {
+ var option = this.options[i];
+
+ // get the option and option text elements for this option
+ var optionElement = this.optionElements[i].option;
+ var optionTextElement = this.optionElements[i].text;
+
+ // figure out the option state
+ var optionStateName = this.isSelected(option) ? "Checked" : "Unchecked";
+ if (!this.enabled) {
+ optionStateName += "Disabled";
+ } else if (this.focusedOption == option) {
+ optionStateName += "Focus";
+ } else {
+ optionStateName += "Normal";
+ }
+
+ // set option element class names
+ if (this.multipleSelection) {
+ this.setClassName(optionElement, "SelectionListOptionMulti SelectionListOptionMulti" + optionStateName);
+ } else {
+ this.setClassName(optionElement, "SelectionListOptionSingle SelectionListOptionSingle" + optionStateName);
+ }
+
+ // set option text class names
+ this.setClassName(optionTextElement, "SelectionListOptionText SelectionListOptionText" + stateName);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/SelectionMenu.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,204 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The SelectionMenu class implements a single or multi selection control
+// that lets users select one or more options from a menu.
+
+// Constructor.
+function SelectionMenu(id, caption, options, multipleSelection, selected) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, options, multipleSelection, selected);
+ }
+}
+
+// SelectionMenu inherits from SelectionControl.
+SelectionMenu.prototype = new SelectionControl(UI_NO_INIT_ID);
+
+// Reference to the peer HTML element.
+SelectionControl.prototype.peerElement = null;
+
+// Array for tracking option elements.
+SelectionMenu.prototype.optionElements = null;
+
+// Initializer - called from constructor.
+SelectionMenu.prototype.init = function(id, caption, options, multipleSelection, selected) {
+ uiLogger.debug("SelectionMenu.init(" + id + ", " + caption + ", " + options + ", " + multipleSelection + ", " + selected + ")");
+
+ // call superclass initializer
+ SelectionControl.prototype.init.call(this, id, caption, options, multipleSelection, selected);
+
+ // create the control
+ this.peerElement = document.createElement("select");
+ this.peerElement.multiple = multipleSelection;
+ this.controlElement.appendChild(this.peerElement);
+
+ // init option elements array
+ this.optionElements = [];
+
+ // update the option elements to match the options in this control
+ this.updateOptionElements();
+
+ // bind event listeners
+ var self = this;
+ this.peerElement.addEventListener("focus", function() { self.focusStateChanged(true); }, false);
+ this.peerElement.addEventListener("blur", function() { self.focusStateChanged(false); }, false);
+ this.peerElement.addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
+ this.peerElement.addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
+ this.peerElement.addEventListener("change", function() { self.selectionChanged(); }, false);
+}
+
+// Returns the enabled state.
+SelectionMenu.prototype.isEnabled = function() {
+ return !this.peerElement.disabled;
+}
+
+// Sets the enabled state.
+SelectionMenu.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("SelectionMenu.setEnabled(" + enabled + ")");
+ this.peerElement.disabled = !enabled;
+}
+
+// Sets the focused state for the control.
+// Note: This may not always succeed.
+SelectionMenu.prototype.setFocused = function(focused) {
+ uiLogger.debug("SelectionMenu.setFocused(" + focused + ")");
+ if (focused) {
+ this.peerElement.focus();
+ } else {
+ this.peerElement.blur();
+ }
+}
+
+// Sets the currently selected options. Pass a single option in a single selection
+// control or an array of selected controls in a multiple selection control. To
+// deselect all options pass null in a single selection control and an empty array
+// in a multiple selection control.
+SelectionMenu.prototype.setSelected = function(selected) {
+ // call superclass setSelected()
+ SelectionControl.prototype.setSelected.call(this, selected);
+
+ // iterate through the options and set the selected state
+ // on the corresponding option element
+ for (var i = 0; i < this.options.length; i++) {
+ this.optionElements[i].selected = this.isSelected(this.options[i]);
+ }
+}
+
+// Sets the options in the control.
+SelectionMenu.prototype.setOptions = function(options) {
+ // call superclass setOptions()
+ SelectionControl.prototype.setOptions.call(this, options);
+ this.updateOptionElements();
+}
+
+// Updates the option elements for the peer select element.
+SelectionMenu.prototype.updateOptionElements = function() {
+ // start by removing all current options from the select element
+ while (this.peerElement.firstChild != null) {
+ this.peerElement.removeChild(this.peerElement.firstChild);
+ }
+
+ // iterate through the options and add (and possibly create) a
+ // properly configured option element for each option
+ for (var i = 0; i < this.options.length; i++) {
+ // do we need to create a new option element?
+ if (i == this.optionElements.length) {
+ this.optionElements.push(document.createElement("option"));
+ }
+
+ // get the option and option element we're working on
+ var option = this.options[i];
+ var optionElement = this.optionElements[i];
+
+ // set the state for this option element and add it to the
+ // peer select element
+ optionElement.text = option.text;
+ optionElement.selected = this.isSelected(option);
+ this.peerElement.appendChild(optionElement);
+ }
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Callback for selection change events.
+SelectionMenu.prototype.selectionChanged = function() {
+ uiLogger.debug("SelectionControl.selectionChanged()");
+
+ // update the selected options array or reference
+ this.selected = (this.multipleSelection) ? [] : null;
+ for (var i = 0; i < this.options.length; i++) {
+ if (this.optionElements[i].selected) {
+ if (this.multipleSelection) {
+ this.selected.push(this.options[i]);
+ } else {
+ this.selected = this.options[i];
+ break;
+ }
+ }
+ }
+
+ // notify event listeners
+ this.fireEvent(this.createEvent("SelectionChanged", this.getSelected()));
+}
+
+// Updates the style of the control to reflects the state of the control.
+SelectionMenu.prototype.updateStyleFromState = function() {
+ uiLogger.debug("SelectionMenu.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.controlElement, "ControlElement");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
+ this.setClassName(this.captionElement, "ControlCaption ControlCaption" + stateName);
+
+ // set select and option element class names
+ var peerStateName = this.isEnabled() ? stateName : "Disabled";
+ this.setClassName(this.peerElement, "SelectionMenu SelectionMenu" + peerStateName);
+ for (var i = 0; i < this.options.length; i++) {
+ var option = this.optionElements[i];
+ this.setClassName(option, "SelectionMenuOption SelectionMenuOption" + peerStateName);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/Separator.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,119 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The Separator class is used to provide a visual separator in a list.
+
+// Constructor.
+function Separator(id) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id);
+ }
+}
+
+// Separator inherits from Control.
+Separator.prototype = new Control(UI_NO_INIT_ID);
+
+// Reference to the separator element.
+Separator.prototype.separatorElement = null;
+
+// Separator row element.
+Separator.prototype.tableRowElement = null;
+
+// Left cell element.
+Separator.prototype.tableLeftCellElement = null;
+
+// Center cell element.
+Separator.prototype.tableCenterCellElement = null;
+
+// Right cell element.
+Separator.prototype.tableRightCellElement = null;
+
+// Initializer - called from constructor.
+Separator.prototype.init = function(id) {
+ uiLogger.debug("Separator.init(" + id + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, null);
+
+ // remove caption and control elements
+ this.assemblyElement.removeChild(this.captionElement);
+ this.assemblyElement.removeChild(this.controlElement);
+
+ // create separator
+ this.separatorElement = document.createElement("table");
+ this.tableRowElement = document.createElement("tr");
+ this.tableLeftCellElement = document.createElement("td");
+ this.tableCenterCellElement = document.createElement("td");
+ this.tableRightCellElement = document.createElement("td");
+ this.tableRowElement.appendChild(this.tableLeftCellElement);
+ this.tableRowElement.appendChild(this.tableCenterCellElement);
+ this.tableRowElement.appendChild(this.tableRightCellElement);
+ this.separatorElement.appendChild(this.tableRowElement);
+ this.assemblyElement.appendChild(this.separatorElement);
+
+ // update style
+ this.updateStyleFromState();
+}
+
+// Returns the enabled state for the control.
+Separator.prototype.isEnabled = function() {
+ return true;
+}
+
+// Returns the focusable state for the control.
+Separator.prototype.isFocusable = function() {
+ return false;
+}
+
+// Updates the style of the control to reflects the state of the control.
+Separator.prototype.updateStyleFromState = function() {
+ uiLogger.debug("Separator.updateStyleFromState()");
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssemblyNormal");
+ this.setClassName(this.separatorElement, "Separator");
+ this.setClassName(this.tableRowElement, "SeparatorRow");
+ this.setClassName(this.tableLeftCellElement, "SeparatorLeftCell");
+ this.setClassName(this.tableCenterCellElement, "SeparatorCenterCell");
+ this.setClassName(this.tableRightCellElement, "SeparatorRightCell");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/TabView.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,155 @@
+
+function TabView(id, caption) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption);
+ }
+}
+
+// TabView inherits from View.
+TabView.prototype = new View(UI_NO_INIT_ID);
+
+// The caption of this view; null if none.
+TabView.prototype.caption = null;
+
+// The caption element of this view.
+TabView.prototype.captionElement = null;
+
+// The caption element of this view.
+TabView.prototype.captionTextElement = null;
+
+// Root HTML element for controls.
+TabView.prototype.tabViewRootElement = null;
+
+// HTML element for tabs heading .
+TabView.prototype.tabsElement = null;
+
+// HTML element for tab content.
+TabView.prototype.tabContent = null;
+
+// List of tabs in the view.
+TabView.prototype.tabs = [];
+
+// List of tab captions in the view.
+TabView.prototype.tabCaptions = [];
+
+// List of tab captions in the view.
+TabView.prototype.tabHeadElements = [];
+
+// Current tab in this view
+TabView.prototype.currentTab = null;
+
+// Initializer for TabView.
+TabView.prototype.init = function(id, caption) {
+ uiLogger.debug("ListView.init(" + id + ", " + caption + ")");
+
+ // call superclass initializer
+ View.prototype.init.call(this, id);
+
+ // init control array
+ this.controls = [];
+
+ // set style class name for root element - reuse ListView style
+ this.rootElement.className = "ListView";
+
+ // create caption and caption text elements
+ this.captionElement = document.createElement("div");
+ this.captionElement.className = "ListViewCaption";
+ this.captionTextElement = document.createElement("div");
+ this.captionTextElement.className = "ListViewCaptionText";
+ this.captionElement.appendChild(this.captionTextElement);
+ this.rootElement.appendChild(this.captionElement);
+
+ // create root element for controls and add to the view root element
+ this.tabViewRootElement = document.createElement("div");
+ this.tabViewRootElement.className = "ListViewControlList";
+ this.tabsElement = document.createElement("div");
+ this.tabsElement.className = "ListViewCaption";
+ this.tabContent = document.createElement("div");
+ this.tabViewRootElement.appendChild(this.tabsElement);
+ this.tabViewRootElement.appendChild(this.tabContent);
+ this.rootElement.appendChild(this.tabViewRootElement);
+
+ // set the caption
+ this.setCaption(caption);
+}
+
+// Returns the caption; null if none.
+TabView.prototype.getCaption = function() {
+ return this.caption;
+}
+
+// Sets the caption; null if none.
+TabView.prototype.setCaption = function(caption) {
+ uiLogger.debug("ListView.setCaption(" + caption + ")");
+
+ // set the display style
+ this.captionElement.style.display = (caption == null) ? "none" : "block";
+
+ // set the caption
+ this.caption = caption;
+ this.captionTextElement.innerHTML = (caption == null) ? "" : caption;
+}
+
+// Add a ListView as a tab
+TabView.prototype.addTab = function(tab) {
+ this.addTab(tab, tab.getCaption());
+}
+
+// Add a ListView as a tab specifying a label
+TabView.prototype.addTab = function(tab, label) {
+ this.tabs.push(tab);
+ this.tabCaptions.push(label);
+ // create a element for the tab heading
+ var tabHead = document.createElement("div");
+ tabHead.className = "TabViewTabCaption";
+ tabHead.innerHTML = label;
+ this.tabHeadElements.push(tabHead);
+ this.tabsElement.appendChild(this.tabHead);
+ if ( this.currentTab == null ) {
+ setCurrentTab(0);
+ }
+}
+
+TabView.prototype.setCurrentTab = function(newCurrentTab) {
+ // clear focus on current tab
+
+ // store the current tab index
+ this.currentTab = newCurrentTab;
+
+ // set focus on current tab
+
+ // update the content element
+ this.tabContent.replaceNode(this.tabs[currentTab].rootElement);
+}
+
+
+TabView.prototype.bindTabActionListeners = function() {
+ var self = this;
+ // bind left-right actions to switching tabs
+ this.rootElement.addEventListener("keydown", function(event) { self.handleKeyPress(event); }, true); // capture phase
+// for ( var t = 0; t < this.tabs.length; t++ ) {
+// // bind tab listeners
+// this.tabHeadElements[t].addEventListener("focus", function() { self.focusStateChanged(true); }, false); // bubble phase
+// this.tabHeadElements[t].addEventListener("blur", function() { self.focusStateChanged(false); }, false);
+// this.tabHeadElements[t].addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
+// this.tabHeadElements[t].addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
+// this.tabHeadElements[t].addEventListener("mousedown", function(event){ self.setCurrentTab(t);}, true);
+// }
+}
+
+TabView.prototype.handleKeyPress = function(event) {
+ if (event.keyCode == 37 ) { // left
+ if ( this.currentTab > 0 ) {
+ this.setCurrentTab(this.currentTab-1);
+ }
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ if (event.keyCode == 39 ) { // right
+ if ( this.currentTab < this.tabs.length-1 ) {
+ this.setCurrentTab(this.currentTab+1);
+ }
+ event.stopPropagation();
+ event.preventDefault();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/TextArea.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,96 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The TextArea class implements a multi line text entry control.
+
+// Constructor.
+function TextArea(id, caption, value, rows) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, value, rows);
+ }
+}
+
+// TextArea inherits from TextEntryControl.
+TextArea.prototype = new TextEntryControl(UI_NO_INIT_ID);
+
+// Initializer - called from constructor.
+TextArea.prototype.init = function(id, caption, value, rows) {
+ uiLogger.debug("TextArea.init(" + id + ", " + caption + ", " + value + ", " + rows + ")");
+
+ // call superclass initializer
+ TextEntryControl.prototype.init.call(this, id, caption);
+
+ // create the peer element
+ this.peerElement = document.createElement("textarea");
+ // default rowcount is 3 if not defined
+ // width always comes from style but is a required attribute
+ this.peerElement.rows = (rows != null) ? rows : 3;
+ this.peerElement.cols = 20;
+ this.controlElement.appendChild(this.peerElement);
+
+ // set the value
+ this.peerElement.value = (value == null) ? "" : value;
+
+ // bind event listeners
+ this.bindTextEntryControlListeners();
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Updates the style of the control to reflects the state of the control.
+TextArea.prototype.updateStyleFromState = function() {
+ uiLogger.debug("TextArea.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.controlElement, "ControlElement");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
+ this.setClassName(this.captionElement, "ControlCaption ControlCaption" + stateName);
+
+ // set peer element class names
+ var peerStateName = this.isEnabled() ? stateName : "Disabled";
+ this.setClassName(this.peerElement, "TextArea TextArea" + stateName);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/TextEntryControl.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,125 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The TextEntryControl class is an abstract base class for the single and multi-
+// line text entry controls TextField and TextArea. Don't use TextEntryControl
+// directly.
+
+// Constructor.
+function TextEntryControl(id, caption) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption);
+ }
+}
+
+// TextEntryControl inherits from Control.
+TextEntryControl.prototype = new Control(UI_NO_INIT_ID);
+
+// Reference to the peer HTML element.
+TextEntryControl.prototype.peerElement = null;
+
+// Initializer - called from constructor.
+TextEntryControl.prototype.init = function(id, caption) {
+ uiLogger.debug("TextEntryControl.init(" + id + ", " + caption + ")");
+
+ // call superclass initializer
+ Control.prototype.init.call(this, id, caption);
+}
+
+// Common event listeners hookup function called from subclasses.
+TextEntryControl.prototype.bindTextEntryControlListeners = function() {
+ var self = this;
+ this.peerElement.addEventListener("focus", function() { self.focusStateChanged(true); }, false);
+ this.peerElement.addEventListener("blur", function() { self.focusStateChanged(false); }, false);
+ this.peerElement.addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
+ this.peerElement.addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
+ this.peerElement.addEventListener("change", function() { self.valueChanged(); }, false);
+}
+
+// Returns the enabled state.
+// Override this in subclasses as required to implement the state change.
+TextEntryControl.prototype.isEnabled = function() {
+ return !this.peerElement.readOnly;
+}
+
+// Sets the enabled state.
+// Override this in subclasses as required to implement the state change.
+TextEntryControl.prototype.setEnabled = function(enabled) {
+ uiLogger.debug("TextEntryControl.setEnabled(" + enabled + ")");
+ this.peerElement.readOnly = !enabled;
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Returns the control text.
+TextEntryControl.prototype.getText = function() {
+ return this.peerElement.value;
+}
+
+// Sets the text for the control.
+TextEntryControl.prototype.setText = function(text) {
+ this.peerElement.value = text;
+}
+
+// Returns the focusable state for the control.
+TextEntryControl.prototype.isFocusable = function() {
+ // text entry controls are always focusable
+ return true;
+}
+
+// Sets the focused state for the control.
+// Note: This may not always succeed.
+TextEntryControl.prototype.setFocused = function(focused) {
+ uiLogger.debug("TextEntryControl.setFocused(" + focused + ")");
+ if (focused) {
+ this.peerElement.focus();
+ } else {
+ this.peerElement.blur();
+ }
+}
+
+// Callback for value change events.
+TextEntryControl.prototype.valueChanged = function() {
+ uiLogger.debug("TextEntryControl.valueChanged()");
+ // notify event listeners
+ this.fireEvent(this.createEvent("ValueChanged", this.peerElement.value));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/TextField.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,93 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The TextField class implements a single line text entry control.
+
+// Constructor.
+function TextField(id, caption, value, masked) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id, caption, value, masked);
+ }
+}
+
+// TextField inherits from TextEntryControl.
+TextField.prototype = new TextEntryControl(UI_NO_INIT_ID);
+
+// Initializer - called from constructor.
+TextField.prototype.init = function(id, caption, value, masked) {
+ uiLogger.debug("TextField.init(" + id + ", " + caption + ", " + value + ", " + masked + ")");
+
+ // call superclass initializer
+ TextEntryControl.prototype.init.call(this, id, caption);
+
+ // create the peer element
+ this.peerElement = document.createElement("input");
+ this.peerElement.type = masked ? "password" : "text";
+ this.controlElement.appendChild(this.peerElement);
+
+ // set the value
+ this.peerElement.value = (value == null) ? "" : value;
+
+ // bind event listeners
+ this.bindTextEntryControlListeners();
+
+ // update the style
+ this.updateStyleFromState();
+}
+
+// Updates the style of the control to reflects the state of the control.
+TextField.prototype.updateStyleFromState = function() {
+ uiLogger.debug("TextField.updateStyleFromState()");
+
+ // determine the state name
+ var stateName = this.getStyleStateName();
+
+ // set element class names
+ this.setClassName(this.rootElement, "Control");
+ this.setClassName(this.controlElement, "ControlElement");
+ this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
+ this.setClassName(this.captionElement, "ControlCaption ControlCaption" + stateName);
+
+ // set peer element class names
+ var peerStateName = this.isEnabled() ? stateName : "Disabled";
+ this.setClassName(this.peerElement, "TextField TextField" + peerStateName);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/UIElement.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,114 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The UIElement class is the base class for all user interface elements.
+
+// Constructor.
+function UIElement(id) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id);
+ }
+}
+
+// UI element identifier.
+UIElement.prototype.id = null;
+
+// Root HTML element in the UI element.
+UIElement.prototype.rootElement = null;
+
+// Initializer for UIElement.
+UIElement.prototype.init = function(id) {
+ uiLogger.debug("UIElement.init(" + id + ")");
+
+ // copy identifier
+ this.id = id;
+
+ // init event listener array
+ this.eventListeners = [];
+
+ // create the root element
+ this.rootElement = document.createElement("div");
+ if (id != null) {
+ this.rootElement.id = id;
+ }
+}
+
+// Returns an array containing the current event listeners.
+UIElement.prototype.getEventListeners = function() {
+ return this.eventListeners;
+}
+
+// Adds an event listener.
+UIElement.prototype.addEventListener = function(eventType, listener) {
+ var listenerDef = { type: eventType, listener: listener };
+ this.eventListeners.push(listenerDef);
+}
+
+// Removes an event listener.
+UIElement.prototype.removeEventListener = function(eventType, listener) {
+ // iterate through current listeners and remove the specified
+ // listener when its found
+ for (var i = 0; i < this.eventListeners.length; i++) {
+ var listenerDef = this.eventListeners[i];
+ if ((listenerDef.type == eventType) &&
+ (listenerDef.listener == listener)) {
+ this.eventListeners.splice(i, 1);
+ return;
+ }
+ }
+}
+
+// Factory method for an event object where this object is the source object.
+UIElement.prototype.createEvent = function(type, value) {
+ return { source: this, type: type, value: value };
+}
+
+// Fires an event to all listeners.
+UIElement.prototype.fireEvent = function(event) {
+ // iterate through all event listeners and notify them of the event
+ for (var i = 0; i < this.eventListeners.length; i++) {
+ var listenerDef = this.eventListeners[i];
+ if (listenerDef.type == null || listenerDef.type == event.type) {
+ listenerDef.listener.call(this, event);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/UIInit.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,49 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The UIInit script is included before the rest of the UI scripts to setup
+// any resources needed by the UI toolkit.
+
+// Create UI logger.
+var uiLogger = new Logger();
+uiLogger.level = uiLogger.LOG_LEVEL_DEBUG;
+uiLogger.filter = ["QECR"];
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/UIManager.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,277 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+
+///////////////////////////////////////////////////////////////////////////////
+// The UI manager manages a set of views and other user interface elements.
+
+// Constructor.
+function UIManager(viewParentElement, scrollbarParentElement, enableScrollBar, delayInit) {
+ uiLogger.debug("UIManager(" + viewParentElement + ", " + scrollbarParentElement + ")");
+ if (delayInit == null) {
+ this.init(viewParentElement, enableScrollBar, scrollbarParentElement);
+ }
+}
+
+// Parent element for views.
+UIManager.prototype.viewParentElement = null;
+
+// Parent element for scrollbar.
+UIManager.prototype.scrollbarParentElement = null;
+
+// The currently displayed view.
+UIManager.prototype.currentView = null;
+
+// Reference to the scrollbar.
+UIManager.prototype.scrollbar = null;
+
+// Current scroll Y position.
+UIManager.prototype.scrollY = -1;
+
+// Current viewport height.
+UIManager.prototype.viewportHeight = -1;
+
+// Current document height.
+UIManager.prototype.documentHeight = -1;
+
+// Timer identifier or null if no active timer.
+UIManager.prototype.timerId = null;
+
+// Interval for timer ticks for the UI manager timer (in milliseconds)
+UIManager.prototype.TIMER_INTERVAL = 250;
+
+// Reference to the notification popup used to displays notifications.
+UIManager.prototype.notificationPopup = null;
+
+// is scrollbar enabled
+UIManager.prototype.enableScrollBar = null;
+
+// View switch animation
+UIManager.prototype.viewSwitchAnimation = false;
+UIManager.prototype.viewSwitchTimer = null;
+UIManager.prototype.viewSwitchDivPos = 0;
+UIManager.prototype.VIEW_SWITCH_TIMER_INTERVAL = 25;
+
+// init function
+UIManager.prototype.init = function(viewParentElement, enableScrollBar, scrollbarParentElement) {
+ this.enableScrollBar = enableScrollBar;
+
+ // parent element for views
+ if (viewParentElement == null) {
+ // create a parent for views
+ this.viewParentElement = document.createElement("div");
+ this.viewParentElement.className = "ViewContainer";
+ document.body.appendChild(this.viewParentElement);
+ }
+ else {
+ this.viewParentElement = viewParentElement;
+ }
+
+ // parent element for scrollbar
+ if (enableScrollBar) {
+ if (scrollbarParentElement == null) {
+ // create a parent for the scrollbar
+ this.scrollbarParentElement = document.createElement("div");
+ this.scrollbarParentElement.className = "DocumentScrollbarContainer";
+ document.body.appendChild(this.scrollbarParentElement);
+ }
+ else {
+ this.scrollbarParentElement = scrollbarParentElement;
+ }
+ }
+
+ // currently selected view
+ this.currentView = null;
+
+ // create the notification popup
+ // the notification popup adds itself as a child element to the document body
+ this.notificationPopup = new NotificationPopup();
+
+ // create scrollbar
+ if (enableScrollBar) {
+ this.scrollbar = new Scrollbar(this.scrollbarParentElement);
+ }
+
+ // setup scrollbar tracking
+ var self = this;
+ this.startTimer();
+ if (enableScrollBar) {
+ window.addEventListener("resize", function(){
+ self.updateScrollbar();
+ }, false);
+ window.addEventListener("scroll", function(){
+ self.updateScrollbar();
+ }, false);
+ }
+}
+
+// Returns the current view.
+UIManager.prototype.getView = function() {
+ return this.currentView;
+}
+
+// Switches to the specified view.
+UIManager.prototype.setView = function(view){
+ uiLogger.debug("View set to " + view.id);
+ if ( this.viewSwitchTimer != null ) {
+ return;
+ }
+ if (this.viewSwitchAnimation && this.currentView != null) {
+ var self = this;
+ this.viewSwitchDivPos = 0;
+ this.viewSwitchTimer = setInterval(function(){
+ self.animateViewSwitch(view);
+ }, this.VIEW_SWITCH_TIMER_INTERVAL);
+ }
+ else {
+ this.doSetView(view);
+ }
+}
+
+UIManager.prototype.animateViewSwitch = function(view) {
+ if (this.viewSwitchDivPos + window.innerWidth < 0 ) {
+ clearTimeout(this.viewSwitchTimer);
+ var tmp = this.currentView;
+ this.doSetView(view);
+ tmp.rootElement.style.left = null;
+ this.viewSwitchTimer = null;
+ }
+ else {
+ this.viewSwitchDivPos -= 25;
+ this.currentView.rootElement.style.left = this.viewSwitchDivPos;
+ }
+}
+
+
+UIManager.prototype.doSetView = function(view) {
+ // remove the current view from the parent element
+ if (this.currentView != null) {
+ this.viewParentElement.removeChild(this.currentView.rootElement);
+ }
+
+ // reset scroll
+ window.scrollTo(0, 0);
+
+ // add the new view to the parent element
+ if (view != null) {
+ this.currentView = view;
+ this.currentView.resetControlFocusStates();
+ this.viewParentElement.appendChild(this.currentView.rootElement);
+ }
+
+ // update scrollbar
+ if (this.enableScrollBar) {
+ this.updateScrollbar();
+ }
+
+ // focus the first focusable control
+ // a timer is used to prevent unwanted focus shift
+ setTimeout(function() { view.focusFirstControl(); }, 1);
+}
+
+// Updates the scrollbar.
+UIManager.prototype.updateScrollbar = function() {
+ if (this.enableScrollBar) {
+ // get current viewport and document position and dimensions
+ var scrollY = window.scrollY;
+ var viewportHeight = window.innerHeight;
+ var documentHeight = Math.max(document.documentElement.scrollHeight, document.height);
+
+ // check if the scroll position or view has changed
+ if (this.scrollY != scrollY ||
+ this.viewportHeight != viewportHeight ||
+ this.documentHeight != documentHeight) {
+ // scroll position or view has changed
+ this.scrollY = scrollY;
+ this.viewportHeight = viewportHeight;
+ this.documentHeight = documentHeight;
+
+ // update the scrollbar
+ this.scrollbar.update(scrollY, viewportHeight, documentHeight);
+ uiLogger.debug("Scrollbar updated");
+ }
+ }
+}
+
+// Starts the view manager timer.
+UIManager.prototype.startTimer = function() {
+ if (this.timerId == null) {
+ uiLogger.debug("UIManager timer started");
+ var self = this;
+ // setup the timer
+ this.timerId = setInterval(function() { self.onTimer(); }, this.TIMER_INTERVAL);
+ } else {
+ uiLogger.warn("UIManager timer already running");
+ }
+}
+
+// Stops the view manager timer.
+UIManager.prototype.stopTimer = function() {
+ if (this.timerId != null) {
+ // stop the timer
+ clearTimeout(this.timerId);
+ this.timerId = null;
+ } else {
+ uiLogger.warn("UIManager timer already stopped");
+ }
+}
+
+// Timer callback function.
+UIManager.prototype.onTimer = function() {
+ if (this.enableScrollBar) {
+ // make sure the scrollbar is up to date
+ this.updateScrollbar();
+ }
+}
+
+// Displays a notification.
+UIManager.prototype.showNotification = function(displayTime, type, text, progress) {
+ uiLogger.debug("UIManager.showNotification(" + displayTime + ", " + type + ", " + text + ", " + progress + ")");
+ // use the notification popup to show the notification
+ this.notificationPopup.showNotification(displayTime, type, text, progress);
+}
+
+// Hides the currently displayed notification.
+UIManager.prototype.hideNotification = function() {
+ uiLogger.debug("UIManager.hideNotification()");
+ // hide the notification popup
+ this.notificationPopup.hideNotification();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/UI/View.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,142 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// The View class is an abstract base class for views in the UI toolkit.
+// Don't use the View directly - instead use a concrete subclass like ListView.
+
+// Constructor.
+function View(id) {
+ if (id != UI_NO_INIT_ID) {
+ this.init(id);
+ }
+}
+
+// View inherits from UIElement.
+View.prototype = new UIElement(UI_NO_INIT_ID);
+
+// Currently focused control.
+View.prototype.focusedControl = null;
+
+// Allows going back from every view
+View.prototype.previousView = null;
+
+// Initializer - called from constructor.
+View.prototype.init = function(id) {
+ uiLogger.debug("View.init(" + id + ")");
+
+ // call superclass initializer
+ UIElement.prototype.init.call(this, id);
+}
+
+// Returns the currently focused control; null if none.
+View.prototype.getFocusedControl = function() {
+ return this.focusedControl;
+}
+
+// Used to notify the view that the focused control has changed.
+View.prototype.focusedControlChanged = function(control) {
+ uiLogger.debug("View.focusedControlChanged(" + control + ")");
+ this.focusedControl = control;
+ // notify event listeners
+ this.fireEvent(this.createEvent("FocusedControlChanged", this.focusedControl));
+}
+
+// Attempts to focus the first focusable control.
+// Override in subclasses as required.
+View.prototype.focusFirstControl = function() {
+ uiLogger.debug("View.focusFirstControl()");
+}
+
+// Attempts to reset all control focus states.
+// Override in subclasses as required.
+View.prototype.resetControlFocusStates = function() {
+ uiLogger.debug("View.resetControlFocusStates()");
+}
+
+
+// ////////////////////////////////////////////////////////////////////
+// Added functions
+
+// abstract function for setting up menu
+View.prototype.setupMenu = function() {
+}
+
+// set up soft keys. Default implementation sets right soft
+// key to Back if the previous view is set
+View.prototype.setupSoftKeys = function() {
+ if (window.widget) {
+ if (this.previousView != null) {
+ var self = this;
+ menu.setRightSoftkeyLabel("Back", function(){self.goBack();});
+ } else {
+ menu.setRightSoftkeyLabel();
+ }
+ }
+}
+
+// show the view - sets up soft keys
+View.prototype.show = function () {
+ this.setupSoftKeys();
+ this.update(false);
+ uiManager.setView(this);
+}
+
+// abstract function for updating page content
+View.prototype.update = function(forceUpdate){
+}
+
+
+// Default back button handler takes us to previous view
+// if one is set
+View.prototype.goBack = function() {
+ if ( this.previousView != null ) {
+ // transition looks funky
+ if (window.widget) {
+ widget.prepareForTransition("fade");
+ }
+ this.previousView.show();
+ if (window.widget) {
+ widget.performTransition();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/Utils/Logger.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,117 @@
+/*
+© Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (ÒNokiaÓ) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under NokiaÕs copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// Logger utility class that uses the Firebug console class.
+
+// Constructor (everything is static so this is empty).
+function Logger() {
+ // Set default logger level.
+ this.level = this.LOG_LEVEL_OFF;
+}
+
+// Logger levels.
+Logger.prototype.LOG_LEVEL_DEBUG = 0;
+Logger.prototype.LOG_LEVEL_INFO = 1;
+Logger.prototype.LOG_LEVEL_WARN = 2;
+Logger.prototype.LOG_LEVEL_ERROR = 3;
+Logger.prototype.LOG_LEVEL_OFF = 4;
+
+Logger.prototype.level = null;
+Logger.prototype.filter = null;
+
+// Disable logging on other browsers except Firefox.
+Logger.prototype.enabled = (navigator.userAgent.indexOf("Firefox") != -1);
+
+// Dumps an objects properties and methods to the console.
+Logger.prototype.dump = function(obj) {
+ if (this.enabled) {
+ console.dir(obj);
+ }
+}
+
+// Dumps a stracktrace to the console.
+Logger.prototype.trace = function() {
+ if (this.enabled) {
+ console.trace();
+ }
+}
+
+// Prints a debug message to the console.
+Logger.prototype.debug = function(str) {
+ if (this.enabled && this.level <= this.LOG_LEVEL_DEBUG) {
+ if (this.filter == null) {
+ console.debug(str);
+ } else {
+ var show = false;
+ for (i in this.filter) {
+ if (str.indexOf(this.filter[i]) >= 0) {
+ show = true;
+ break;
+ }
+ }
+ if (show) {
+ console.debug(str);
+ }
+ }
+ }
+}
+
+// Prints an info message to the console.
+Logger.prototype.info = function(str) {
+ if (this.enabled && this.level <= this.LOG_LEVEL_INFO) {
+ console.info(str);
+ }
+}
+
+// Prints a warning message to the console.
+Logger.prototype.warn = function(str) {
+ if (this.enabled && this.level <= this.LOG_LEVEL_WARN) {
+ console.warn(str);
+ }
+}
+
+// Prints an error message to the console.
+Logger.prototype.error = function(str) {
+ if (this.enabled && this.level <= this.LOG_LEVEL_ERROR) {
+ console.error(str);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/WRTKit/WRTKit.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,91 @@
+/*
+� Copyright 2008 Nokia Corporation. All rights reserved.
+
+IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
+Widget files.
+
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
+Widgets.
+
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
+redistributions of the WRTKit and Example files.
+
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
+may be incorporated.
+
+The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// This script includes the WRTKit for use in a widget.
+
+// WRTKit version (major.minor.revision, e.g. 1.0.0).
+var WRTKIT_VERSION_MAJOR = 1;
+var WRTKIT_VERSION_MINOR = 0;
+var WRTKIT_VERSION_REVISION = 0;
+var WRTKIT_RESOURCE_DIRECTORY = "WRTKit/Resources/";
+
+// Include util script files.
+includeScript("WRTKit/Utils/Logger.js");
+
+// Include UI visual definition.
+includeStyleSheet("WRTKit/Resources/UI.css");
+
+// Include all UI toolkit script files.
+var UI_NO_INIT_ID = "UI_NO_INIT_ID";
+
+includeScript("WRTKit/UI/UIInit.js");
+includeScript("WRTKit/UI/UIElement.js");
+includeScript("WRTKit/UI/Scrollbar.js");
+includeScript("WRTKit/UI/NotificationPopup.js");
+includeScript("WRTKit/UI/UIManager.js");
+includeScript("WRTKit/UI/View.js");
+includeScript("WRTKit/UI/ListView.js");
+includeScript("WRTKit/UI/Control.js");
+includeScript("WRTKit/UI/Separator.js");
+includeScript("WRTKit/UI/Label.js");
+includeScript("WRTKit/UI/ContentPanel.js");
+includeScript("WRTKit/UI/TextEntryControl.js");
+includeScript("WRTKit/UI/TextField.js");
+includeScript("WRTKit/UI/TextArea.js");
+includeScript("WRTKit/UI/SelectionControl.js");
+includeScript("WRTKit/UI/SelectionMenu.js");
+includeScript("WRTKit/UI/SelectionList.js");
+includeScript("WRTKit/UI/ActionControl.js");
+includeScript("WRTKit/UI/FormButton.js");
+includeScript("WRTKit/UI/NavigationButton.js");
+includeScript("WRTKit/UI/TabView.js");
+includeScript("WRTKit/UI/Ajax.js");
+
+// Includes a script file by writing a script tag.
+function includeScript(src) {
+ document.write("<script type=\"text/javascript\" src=\"" + src + "\"></script>");
+}
+
+// Includes a style sheet by writing a style tag.
+function includeStyleSheet(src) {
+ document.write("<style type=\"text/css\"> @import url(\"" + src + "\"); </style>");
+}
Binary file Symbian.org/blueright.gif has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/index.html Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,21 @@
+<html>
+ <head>
+ <title>Symbian.org</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <script type="text/javascript" src="WRTKit/WRTKit.js"></script>
+ <script type="text/javascript" src="FeedUpdateBroker.js"></script>
+ <script type="text/javascript" src="FeedPresentation.js"></script>
+ <script type="text/javascript" src="Forums.js"></script>
+ <script type="text/javascript" src="Login.js"></script>
+ <script type="text/javascript" src="Bugzilla.js"></script>
+ <script type="text/javascript" src="ForumPostForm.js"></script>
+ <script type="text/javascript" src="RssReader.js"></script>
+ <script type="text/javascript" src="Main.js"></script>
+ <style type="text/css">
+ @import url("style.css");
+ </style>
+ <META NAME="Generator" CONTENT="Nokia WRT plug-in for Aptana Studio 1.0.0.36" />
+ </head>
+ <body onload="init()">
+ </body>
+</html>
\ No newline at end of file
Binary file Symbian.org/logo.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/css/menu.css Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,52 @@
+div#softKeysPane {
+ font-weight: bold;
+ background-color: #E1E1E1;
+ height: 20px;
+ background-image: url(../images/top-navigation-bg.png);
+ background-repeat: repeat-x;
+ color: #FFFFFF;
+}
+div#menuPane {
+
+}
+div#menuItemsPane {
+ background-color: #efefef;
+ z-index: 1000;
+ position: absolute;
+ top: 100px;
+ width: 240px;
+ border-top: 1px solid #CCCCCC;
+ display: none;
+}
+#menuItemsPane ul {
+ margin: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+#menuItemsPane li {
+ padding: 4px 2px 2px 4px;
+ height: 14px;
+ border-top: 1px solid #F4F4F4;
+ border-bottom: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ font-weight: bold;
+}
+
+#menuItemsPane li a{
+ text-decoration: none;
+ color: #000000;
+}
+
+#menuItemsPane li.subMenuItem{
+ background-image: url(../images/arrow.png);
+ background-repeat: no-repeat;
+ background-position: right top;
+}
+#menuItemsPane li.s60AppToggle{
+ background-image: url(../images/s60-tiny-icon.png);
+ background-repeat: no-repeat;
+ background-position: right center;
+}
+#menuItemsPane li.exitOrBackBtn{
+ background-color: #D4D4D4;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/css/style.css Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,188 @@
+iframe#widgetIframeWindow {
+ height: 300px;
+ z-index: 1;
+}
+body {
+ margin: 0px;
+ padding: 0px;
+ margin-top: 70px;
+ font-family: "Nokia Sans", Arial, Verdana;
+ font-size: 10px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+#WrapperDiv {
+ width: 100%;
+ min-height: 700px;
+ overflow: hidden;
+}
+
+div#navigation {
+ background-image: url(../images/top-navigation-bg.png);
+ height: 52px;
+ overflow: hidden;
+ position: absolute;
+ width: 100%;
+ left: 0px;
+ top: 0px;
+}
+div#navigation strong{
+ color: #ffffff;
+}
+#device {
+ margin-right: auto;
+ margin-left: auto;
+ width: 10px;
+}
+#DisplayOrientation {
+ height: 34px;
+ width: 250px;
+ margin-right: auto;
+ margin-left: auto;
+ margin-bottom: 10px;
+ background-image: url(../images/display-orientation.png);
+ background-repeat: no-repeat;
+ overflow:hidden;
+ background-color:#FFFFFF;
+}
+
+
+#DisplayOrientation.portrait {
+ background-position: 0px 0px;
+}
+
+#DisplayOrientation.landscape {
+ background-position: 0px -45px;
+}
+
+div#iframePreviewWindow {
+ background-color: #FFFFFF;
+ height: 320px;
+ width: 240px;
+}
+
+div#display {
+ background-image: url(../images/device-right.png);
+ background-repeat: no-repeat;
+ background-position: right top;
+}
+div#displayLeft {
+ background-image: url(../images/device-left.png);
+ background-repeat: no-repeat;
+ background-position: left top;
+ padding-top: 10px;
+ padding-right: 8px;
+ padding-bottom: 0px;
+ padding-left: 9px;
+}
+
+iframe{
+ overflow:hidden;
+}
+#DeviceSettings {
+ position: absolute;
+ top: 0px;
+ z-index: 1000;
+ font-size: 12px;
+ background-color: #ffffff;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-left: 10px;
+ display: block;
+ overflow: hidden;
+ color: #999999;
+ opacity: 0.9;
+ height: 100%;
+ background-image: url(../images/toolbar-bg-shadow.png);
+ background-repeat: repeat-y;
+ background-position: left top;
+}
+div#pullDown {
+ height: 50px;
+ width: 69px;
+ background-repeat: no-repeat;
+ margin-left: -61px;
+ position: absolute;
+ z-index: 1005;
+}
+div#pullDown.down {
+ background-image: url(../images/new-pull-down-btn.png);
+ background-position: 0px -50px;
+}
+div#pullDown.up {
+ background-image: url(../images/new-pull-down-btn.png);
+ background-position: 0px 0px;
+}
+
+#DeviceSettings strong {
+ color: #000000;
+}
+
+#Toolbar {
+ position: fixed;
+ right: 0px;
+ width: 320px;
+ top: 0;
+ height: 100%;
+}
+#pullDown {
+ margin-top: 10px;
+}
+
+
+#save {
+ background-image: url(../images/select-device-tab.png);
+ background-repeat: no-repeat;
+ background-position: center center;
+ font-weight: bold;
+ color: #FFFFFF;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ border-top-width: 2px;
+ border-right-width: 2px;
+ border-bottom-width: 2px;
+ border-left-width: 2px;
+ border-top-style: solid;
+ border-right-style: solid;
+ border-bottom-style: solid;
+ border-left-style: solid;
+ border-top-color: #225311;
+ border-right-color: #3C931E;
+ border-bottom-color: #3C931E;
+ border-left-color: #225311;
+}
+
+#DeviceSettings p {
+ border-bottom: 1px solid #E0E0E0;
+ padding-bottom: 5px;
+ margin-right: 20px;
+ margin-left: 20px;
+ padding-top: 0px;
+ margin-top: 0px;
+ margin-bottom: 8px;
+}
+
+select#deviceResolution {
+ margin-left: 15px;
+ font-size: 13px;
+ width: 200px;
+ border: 1px solid #999999;
+ height: 90px;
+ margin-top: 10px;
+}
+#deviceResolution option {
+ padding: 3px;
+ font-family: "Nokia Sans", "Nokia Sans SemiBold";
+
+}
+#DeviceSettings img {
+ margin-top: 8px;
+}
+label {
+ padding-top: 8px;
+ font-weight: bold;
+ color: #000000;
+}
+#DeviceSettings input {
+ margin-top: 5px;
+}
Binary file Symbian.org/preview/images/arrow.png has changed
Binary file Symbian.org/preview/images/device-bottom.png has changed
Binary file Symbian.org/preview/images/device-left-softkey.png has changed
Binary file Symbian.org/preview/images/device-left.png has changed
Binary file Symbian.org/preview/images/device-right-softkey.png has changed
Binary file Symbian.org/preview/images/device-right.png has changed
Binary file Symbian.org/preview/images/device/5320_main.jpg has changed
Binary file Symbian.org/preview/images/device/5800_main.jpg has changed
Binary file Symbian.org/preview/images/device/6210_main.jpg has changed
Binary file Symbian.org/preview/images/device/6220_main.jpg has changed
Binary file Symbian.org/preview/images/device/6650-2_main.jpg has changed
Binary file Symbian.org/preview/images/device/N95_main.jpg has changed
Binary file Symbian.org/preview/images/device/e51_main.jpg has changed
Binary file Symbian.org/preview/images/device/e66_main.jpg has changed
Binary file Symbian.org/preview/images/device/e71_main.jpg has changed
Binary file Symbian.org/preview/images/device/e90_main.jpg has changed
Binary file Symbian.org/preview/images/device/n78_main.jpg has changed
Binary file Symbian.org/preview/images/device/n79_main.jpg has changed
Binary file Symbian.org/preview/images/device/n82_main.jpg has changed
Binary file Symbian.org/preview/images/device/n85_main.jpg has changed
Binary file Symbian.org/preview/images/device/n95_8gb_main.jpg has changed
Binary file Symbian.org/preview/images/device/n96_main.jpg has changed
Binary file Symbian.org/preview/images/menuItemHover.png has changed
Binary file Symbian.org/preview/images/new-pull-down-btn.png has changed
Binary file Symbian.org/preview/images/s60-tiny-icon.png has changed
Binary file Symbian.org/preview/images/select-device-text.png has changed
Binary file Symbian.org/preview/images/toolbar-bg-shadow.png has changed
Binary file Symbian.org/preview/images/top-navigation-bg.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/nopreview.html Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+</head>
+<body>
+Widget preview is not available for this file, it is not the main html file for the widget.
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/preview_exit.html Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>Preview Exit</title>
+ <style type="text/css">
+ body{
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ }
+ div{
+ margin-top: 50px;
+ background-color: #EFF5FB;
+ padding: 5px;
+ border: 1px solid #A9D0F5;
+ }
+ </style>
+ </head>
+ <body>
+ <div align="center">
+ You have selected the <strong>Exit</strong> option from the widget menu. To see the widget preview, <br/>Refresh <strong>Widget</strong> view.
+ </div>
+ </body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/build.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,681 @@
+/*
+ * Call this function when window is ready
+ */
+ window.onload = function()
+ {
+
+ // Attach events to Resolution Options & Orientation select
+ $('deviceResolution').onchange = function(ele){
+ if(ele.target != undefined)
+ ele = ele.target;
+
+ Emulator.cur_device = ele.options[ele.selectedIndex].value;
+ Emulator.setDeviceLabels(SUPPORTED_DEVICES[Emulator.cur_device]);
+
+ // save the selected device details
+ createCookie('DEVICE_NAME', Emulator.cur_device);
+ }
+
+ /*
+ * Toggle b/w Portrait / Landscape mode
+ */
+ $('DisplayOrientation_portrait').onclick = function(ele){
+
+ if(ele.target != undefined)
+ ele = ele.target;
+ if(Emulator.orientation_mode != 'portrait')
+ Emulator.changeOrientation(ele);
+ }
+
+ $('DisplayOrientation_landscape').onclick = function(ele){
+
+ if(ele.target != undefined)
+ ele = ele.target;
+ if(Emulator.orientation_mode != 'landscape')
+ Emulator.changeOrientation(ele);
+ }
+ $('Toolbar').style.right = "-320px";
+
+
+ // Toggle ToolBar Show/Hide
+ $('pullDown').onclick = function()
+ {
+ if(is_toolbar_hidden)
+ {
+ showDeviceSettings();
+ }
+ else
+ {
+ hideDeviceSettings();
+ }
+ }
+
+ // Toggle ToolBar Show/Hide
+ $('WrapperDiv').onmouseover = function(){
+ if(!is_scrolling && !is_toolbar_hidden)
+ window.setTimeout('hideDeviceSettings()', 1);
+ }
+
+ // Assign Soft-keys trigger to Textual links
+ $("leftSoftKey").onclick = function(){
+ Emulator.triggerChildLSK();
+ }
+ $("rightSoftKey").onclick = function(){
+ Emulator.triggerChildRSK();
+ }
+
+
+ // Assign Soft-keys trigger to Image links
+ $("leftSoftKeyImg").onclick = function(){
+ Emulator.triggerChildLSK();
+ }
+
+ $("rightSoftKeyImg").onclick = function(){
+ Emulator.triggerChildRSK();
+ }
+
+ // Preload Device Information
+ Emulator.loadDeviceSettings();
+
+ // set the Default size to device
+ Emulator.setDeviceSize();
+
+ // set the Menu Pane position
+ Emulator.setMenuPane();
+ }
+
+
+/*
+ * Helper function
+ */
+ function $(str)
+ {
+ return document.getElementById(str);
+ }
+
+
+/*
+ * Emulator, which manages the device interacations
+ */
+
+ var Emulator = {};
+
+ // Default, device screen resolution
+ Emulator.cur_device = 'n78';
+ Emulator.cur_resolution = '240x320';
+ Emulator.device_cover_width = 17;
+ Emulator.device_cover_height = 8;
+
+ Emulator.orientation_changed = false;
+ Emulator.orientation_mode = 'portrait'; // { portrait | landscape }
+
+ // Flag, inidcates Menu Object created/exists in the child window
+ Emulator.is_widgetMenuIntiated = false;
+
+ // Used as a bridge between, Parent window & Child widget
+ Emulator.parentToChild_Reference = null;
+
+ // Interval ID for X-Resize
+ Emulator.interval_X = null;
+
+ // Interval ID for Y-Resize
+ Emulator.interval_Y = null;
+
+ Emulator.path = document.location.pathname;
+
+/*
+ * Change the device resolution
+ */
+
+ Emulator.changeResolution = function(cur_val, to_val)
+ {
+
+ if(!SUPPORTED_DEVICES[this.cur_device]['orientation']){
+
+ // check the Portrait mode
+ $("DisplayOrientation_portrait").checked = true;
+
+ $("DisplayOrientation_landscape").checked = false;
+ $("DisplayOrientation_landscape").disabled = true;
+
+ // update the orientation-mode
+ this.orientation_mode = 'portrait';
+
+
+ // Toggle the Orientation Flag
+ this.orientation_changed = false;
+
+ }
+ else
+ $("DisplayOrientation_landscape").disabled = false;
+
+ if(cur_val == to_val)
+ return false;
+
+ cur_val = cur_val.split('x');
+ cur_val[0] = parseInt(cur_val[0]);
+ cur_val[1] = parseInt(cur_val[1]);
+
+ to_val = to_val.split('x');
+ to_val[0] = parseInt(to_val[0]);
+ to_val[1] = parseInt(to_val[1]);
+
+ // hide the keys, if the OPTION menu is OPEN
+ this.hideDeviceSoftKeys();
+
+ $('widgetIframeWindow').style.height = '100%';
+ $('menuItemsPane').style.width = to_val[0]+'px';
+
+
+ // for X
+ var adjust_x = 0;
+ if(cur_val[0]%10)
+ {
+ // decrease these many pixels
+ adjust_x = ((cur_val[0]%10) * (-1));
+ }
+ else if(to_val[0]%10){
+ // increase these many pixels
+ adjust_x = (to_val[0]%10);
+ }
+
+ cur_val[0] = cur_val[0] + adjust_x;
+ $('iframePreviewWindow').style.width = parseInt(cur_val[0] + adjust_x) + 'px';
+ $('device').style.width = parseInt(cur_val[0] + adjust_x) + this.device_cover_width+'px';
+
+
+ if (cur_val[0] < to_val[0])
+ {
+ this.resizeDivX(cur_val[0], to_val[0], true);
+ }
+ else
+ {
+ this.resizeDivX(cur_val[0], to_val[0], false);
+ }
+
+
+ // for Y
+ var adjust_y = 0;
+ if(cur_val[1]%10)
+ {
+ // decrease these many pixels
+ adjust_y = ((cur_val[1]%10) * (-1));
+ }
+ else if(to_val[1]%10){
+ // increase these many pixels
+ adjust_y = (to_val[1]%10);
+ }
+ cur_val[1] = cur_val[1] + adjust_y;
+
+ $('iframePreviewWindow').style.height = parseInt(cur_val[1] + adjust_y) + 'px';
+ $('device').style.height = parseInt(cur_val[1] + adjust_y) + this.device_cover_height+'px';
+
+ if (cur_val[1] < to_val[1])
+ {
+ this.resizeDivY(cur_val[1], to_val[1], true);
+ }
+ else
+ {
+ this.resizeDivY(cur_val[1], to_val[1], false);
+ }
+
+ }
+
+/*
+ * Resize the device on Horizontally
+ */
+
+ Emulator.resizeDivX = function(from, to, flag)
+ {
+ if(from != to)
+ {
+ var curWidth = $('iframePreviewWindow').style.width;
+ curWidth = parseInt(curWidth.substr(0, (curWidth.length-2)));
+ if(flag)
+ {
+ curWidth = curWidth + 10;
+ to = parseInt(to) - 10;
+ }
+ else
+ {
+ curWidth = curWidth - 10;
+ to = parseInt(to) + 10;
+ }
+ $('iframePreviewWindow').style.width = curWidth + 'px';
+ $('device').style.width = parseInt(curWidth + this.device_cover_width)+'px';
+
+ if(this.interval_X)
+ clearInterval(this.interval_X);
+ this.interval_X = setInterval(function(){ Emulator.resizeDivX(from, to, flag); }, 10);
+ }
+ else{
+ clearInterval(this.interval_X);
+ }
+ }
+
+/*
+ * Resize the device on Vertically
+ */
+
+ Emulator.resizeDivY = function(from, to, flag)
+ {
+ if(from != to)
+ {
+ var curHeight = $('iframePreviewWindow').style.height;
+ curHeight = parseInt(curHeight.substr(0, (curHeight.length-2)));
+ if(flag)
+ {
+ curHeight = curHeight + 10;
+ to = parseInt(to) - 10;
+ }
+ else
+ {
+ curHeight = curHeight - 10;
+ to = parseInt(to) + 10;
+ }
+ $('iframePreviewWindow').style.height = curHeight + 'px';
+ $('device').style.height = parseInt(curHeight+this.device_cover_height)+'px';
+
+ if(this.interval_Y)
+ clearInterval(this.interval_Y);
+ this.interval_Y = setInterval(function(){ Emulator.resizeDivY(from, to, flag); }, 10);
+ }
+ else
+ {
+ clearInterval(this.interval_Y);
+
+ /*
+ * Cross check, why i have written these lines @P-1
+ */
+ if(!this.parentToChild_Reference.menu.is_sfk_disabled)
+ {
+ // show menu Pane
+ Emulator.setMenuPane();
+ $('menuPane').style.display = 'block';
+ }
+
+ }
+ }
+
+/*
+ * Toggle device orienation b/w Landscape & Portrait
+ */
+ Emulator.changeOrientation = function(ele)
+ {
+ if(SUPPORTED_DEVICES[this.cur_device]['orientation'])
+ {
+ // If the device supports Orientation, perform
+ if(this.parentToChild_Reference.widget.isrotationsupported)
+ {
+ // Swap the current resolution value
+ // Width -> Height
+ // height -> Width
+ var cur_val = this.cur_resolution;
+ this.cur_resolution = this.cur_resolution.split('x');
+ this.cur_resolution = this.cur_resolution[1]+'x'+this.cur_resolution[0];
+
+ // Toggle the Orientation Flag
+ this.orientation_changed = (this.orientation_changed) ? false : true;
+
+ // Toggle the Orientation value
+ this.orientation_mode = (this.orientation_mode == 'portrait') ? 'landscape' : 'portrait';
+
+ // Apply the new resolution to the device
+ this.changeResolution(cur_val, this.cur_resolution);
+ }
+ }
+ else{
+ // update the orientation-mode
+ this.orientation_mode = 'portrait';
+
+ // Toggle the Orientation Flag
+ this.orientation_changed = false;
+ }
+ }
+
+
+/*
+ * Set the Device size
+ */
+ Emulator.setDeviceSize = function()
+ {
+ var cur_val;
+ try
+ {
+ this.cur_device = readCookie('DEVICE_NAME');
+ if(this.cur_device == undefined)
+ {
+ this.cur_device = $('deviceResolution').options[0].value;
+ }
+ }
+ catch(e)
+ {
+ this.cur_device = $('deviceResolution').options[0].value;
+ }
+
+ // get Device resolution
+ this.cur_resolution = SUPPORTED_DEVICES[this.cur_device]['display']
+
+
+ // update the Device label values
+ this.setDeviceLabels(SUPPORTED_DEVICES[this.cur_device]);
+
+ // select the corresponding option on the list
+ var select = $('deviceResolution');
+ for(var i=0; i<select.options.length; i++)
+ {
+ if(select.options[i].value == this.cur_device)
+ {
+ select.options[i].selected = true;
+ }
+ }
+
+ // Disable Landscape Mode if the device won't support
+ if(!SUPPORTED_DEVICES[this.cur_device]['orientation'])
+ $("DisplayOrientation_landscape").disabled = true;
+ else
+ $("DisplayOrientation_landscape").disabled = false;
+
+ cur_val = this.cur_resolution.split('x')
+ $('iframePreviewWindow').style.width = parseInt(cur_val[0])+'px';
+ $('iframePreviewWindow').style.height = parseInt(cur_val[1])+'px';
+
+ $('device').style.width = parseInt(cur_val[0]) + this.device_cover_width+'px';
+ $('device').style.height = parseInt(cur_val[1]) + this.device_cover_height+'px';
+ }
+
+
+/*
+ * Set Position of the MenuPane
+ */
+
+ Emulator.setMenuPane = function()
+ {
+ var height = $('iframePreviewWindow').style.height;
+ height = parseInt(height.substr(0, (height.length-2)));
+
+ // decrement height of iframe
+ $('widgetIframeWindow').style.height = (height - 20) + 'px';
+
+ // Adjust the Soft-keys position
+ if ($('menuItemsPane').childNodes[0])
+ {
+ var length = parseInt($('menuItemsPane').childNodes[0].childNodes.length);
+ if (length)
+ $('menuItemsPane').style.top = 55 + parseInt(height - (length * 20)) + 'px';
+
+ }
+ }
+
+/*
+ * Show the Device-Softkeys
+ */
+ Emulator.showDeviceSoftKeys = function()
+ {
+ this.setMenuPane();
+
+ // show menu Pane
+ $('menuPane').style.display = 'block';
+
+ // show menu items pane
+ $('menuItemsPane').style.display = 'block';
+
+ }
+
+
+/*
+ * Hide the Device-Softkeys
+ */
+ Emulator.hideDeviceSoftKeys = function()
+ {
+ var height = $('iframePreviewWindow').style.height;
+ height = parseInt(height.substr(0, (height.length-2)));
+
+ // hide menuPane
+ $('menuPane').style.display = 'none';
+ $('menuItemsPane').style.display = 'none';
+
+ // Set iframe height to IframePreviewWindow
+ $('widgetIframeWindow').style.height = height + 'px';
+ }
+
+/*
+ * Parent-To-Child bride functions
+ * Function to trigger Left-Soft-Key-Event
+ */
+ Emulator.triggerChildLSK = function()
+ {
+ if(this.parentToChild_Reference.menu)
+ {
+ this.parentToChild_Reference.triggeLSK();
+ }
+ }
+
+/*
+ * Function to trigger Right-Soft-Key-Event
+ */
+ Emulator.triggerChildRSK = function()
+ {
+ if(this.parentToChild_Reference.menu)
+ {
+ this.parentToChild_Reference.triggeRSK();
+ }
+ }
+
+/*
+ * Function to trigger Exit
+ */
+ Emulator.triggerExit = function()
+ {
+ // Hide softkeys
+ this.parentToChild_Reference.menu.hideSoftkeys();
+
+
+ // Load the 'preview_exit' file
+ $("widgetIframeWindow").src = 'preview/preview_exit.html';
+
+ // assign the Dummy function to Right soft-key
+ $("rightSoftKey").innerHTML = 'Cancel';
+ $("rightSoftKey").onclick = 'javascript:;';
+
+ }
+
+/*
+ * Function to trigger Menu Hide
+ */
+ Emulator.triggerMenuAutoHide = function()
+ {
+ this.parentToChild_Reference.menu.cancel();
+ }
+
+
+/*
+ * Trigger Menu Show function
+ */
+ Emulator.triggerMenuShow = function(parentId)
+ {
+ this.parentToChild_Reference.menu.showMenu(parentId);
+ }
+
+
+/*
+ * Trigger Menu Show function
+ */
+ Emulator.triggerMenuExit = function(parentId)
+ {
+ this.parentToChild_Reference.menu.exit();
+ }
+
+/*
+ * Trigger Menu Event
+ */
+ Emulator.triggerMenuEvent = function(MenuItemId)
+ {
+ this.parentToChild_Reference.menu.triggeEvent(MenuItemId);
+ }
+
+/*
+ * Load Device Details
+ */
+ Emulator.loadDeviceSettings = function()
+ {
+ if(SUPPORTED_DEVICES)
+ {
+ var select = $('deviceResolution');
+ select.innerHTML = '';
+ for(var key in SUPPORTED_DEVICES)
+ {
+ var option = document.createElement('option');
+ option.text = SUPPORTED_DEVICES[key]['name'];
+ option.value = key;
+ option.className = '6320';
+ select.appendChild(option);
+ }
+ }
+ }
+
+/*
+ * Set Device Details
+ */
+ Emulator.setDeviceLabels = function(row)
+ {
+ $('ModelName').innerHTML = row['name'];
+ $('ModelResolution').innerHTML = row['display'] + ' pixels';
+ $('ModelImage').src = 'preview/images/device/' + row['image'];
+ $('ModelPlatform').innerHTML = row['platform'];
+
+
+ var cur_val = this.cur_resolution;
+ var to_val = row['display'];
+
+ if(this.orientation_changed && SUPPORTED_DEVICES[this.cur_device]['orientation'])
+ {
+ to_val = to_val.split('x');
+ to_val = to_val[1]+'x'+to_val[0];
+ }
+ this.cur_resolution = to_val;
+ this.changeResolution(cur_val, to_val);
+
+ }
+
+ function parentToChild_RSK_Event()
+ {
+ parentToChild_Reference.triggeRightSoftkeyEvent();
+ }
+
+
+ function createCookie(name,value)
+ {
+ var days = 240000;
+ // var domain = "Nokia-WRT";
+ if (days) {
+ var date = new Date();
+ date.setTime(date.getTime()+(days*24*60*60*1000));
+ var expires = "; expires="+date.toGMTString();
+ }
+ else var expires = "";
+ var value = "Nokia_WRT#"+Emulator.path+"#"+name+"="+value;
+ document.cookie = value+expires+"; Emulator.path=/"
+ // + ((domain) ? ';domain=' + domain : '') + ;
+ }
+
+ /**
+ * This function retrieves back the values from the cookies
+ * @param document
+ * @param name
+ * @return
+ */
+ function readCookie(name)
+ {
+ name = "Nokia_WRT#" + Emulator.path + "#" + name;
+ var nameEQ = name + "=";
+ // alert(name);
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
+ if (c.indexOf(nameEQ) == 0) {
+ // alert(c.substring(nameEQ.length,c.length));
+ return c.substring(nameEQ.length,c.length);
+ }
+ }
+ return undefined;
+ }
+
+ var scrollIntervalId = null;
+ var is_scrolling = false;
+ var is_toolbar_hidden = true;
+ function showDeviceSettings()
+ {
+ if(is_scrolling)
+ return false;
+
+ is_scrolling = true;
+ scrollDiv($('Toolbar'), 'down');
+ }
+
+
+ function hideDeviceSettings()
+ {
+ if(is_scrolling)
+ return false;
+
+ is_scrolling = true;
+ scrollDiv($('Toolbar'), 'up');
+ }
+
+ var divHeight = 330;
+ var divWidth = 320;
+ function scrollDiv(ele, type)
+ {
+ var currentRight = ele.style.right;
+ currentRight = parseInt(currentRight.substr(0, (currentRight.length-2)));
+
+ // move up
+ if(type == 'up')
+ {
+ if( currentRight > parseInt(divWidth * (-1)))
+ {
+ ele.style.right = parseInt(currentRight - 5) + 'px';
+
+ if(scrollIntervalId)
+ {
+ clearInterval(scrollIntervalId);
+ }
+ scrollIntervalId = setInterval(function(){ scrollDiv($('Toolbar'), 'up'); }, -10);
+ }
+ else{
+ is_scrolling = false;
+ is_toolbar_hidden = true;
+ clearInterval(scrollIntervalId);
+
+ $('pullDown').className = 'down';
+
+ return false;
+ }
+ }
+ else if(type == 'down')
+ {
+ if( currentRight < 0)
+ {
+ ele.style.right = parseInt(currentRight + 5) + 'px';
+
+ if(scrollIntervalId)
+ {
+ clearInterval(scrollIntervalId);
+ }
+ scrollIntervalId = setInterval(function(){ scrollDiv($('Toolbar'), 'down'); }, -10);
+
+ }
+ else{
+ is_scrolling = false;
+ is_toolbar_hidden = false;
+ clearInterval(scrollIntervalId);
+
+ $('pullDown').className = 'up';
+
+ return false;
+ }
+
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/device.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,174 @@
+/*
+ * Device details
+ */
+var SUPPORTED_DEVICES = new Object();
+
+// N78
+SUPPORTED_DEVICES.N78 = {
+ "name" : "Nokia N78",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "n78_main.jpg",
+ "orientation" : true
+}
+
+// N79
+SUPPORTED_DEVICES.N79 = {
+ "name" : "Nokia N79",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "n79_main.jpg",
+ "orientation" : true
+}
+
+// N82
+SUPPORTED_DEVICES.N82 = {
+ "name" : "Nokia N82",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "n82_main.jpg",
+ "orientation" : true
+}
+
+// N85
+SUPPORTED_DEVICES.N85 = {
+ "name" : "Nokia N85",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "n85_main.jpg",
+ "orientation" : true
+}
+
+// N95
+SUPPORTED_DEVICES.N95 = {
+ "name" : "Nokia N95",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "n95_main.jpg",
+ "orientation" : true
+}
+
+// N95_8GB
+SUPPORTED_DEVICES.N95_8GB = {
+ "name" : "Nokia N95 8GB",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "n95_8gb_main.jpg",
+ "orientation" : true
+}
+
+// N96
+SUPPORTED_DEVICES.N96 = {
+ "name" : "Nokia N96",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "n96_main.jpg",
+ "orientation" : true
+}
+
+// N96-3
+SUPPORTED_DEVICES.N96_3 = {
+ "name" : "Nokia N96-3",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "n96_main.jpg",
+ "orientation" : true
+}
+
+// E51
+SUPPORTED_DEVICES.E51 = {
+ "name" : "Nokia E51",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "e51_main.jpg",
+ "orientation" : true
+}
+
+// E66
+SUPPORTED_DEVICES.E66 = {
+ "name" : "Nokia E66",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "e66_main.jpg",
+ "orientation" : true
+}
+
+// E71
+SUPPORTED_DEVICES.E71 = {
+ "name" : "Nokia E71",
+ "display" : "320x240",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "e71_main.jpg",
+ "orientation" : false
+}
+
+// E90
+SUPPORTED_DEVICES.E90 = {
+ "name" : "Nokia E90 Communicator",
+ "display" : "800x352",
+ "s_display" : "240x320",
+ "platform" : "S60 3rd Edition, Feature Pack 1",
+ "image" : "e90_main.jpg",
+ "orientation" : false
+}
+
+// 5320 XpressMusic
+SUPPORTED_DEVICES.n5320 = {
+ "name" : "Nokia 5320 XpressMusic",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "5320_main.jpg",
+ "orientation" : true
+}
+
+// 6210 Navigator
+SUPPORTED_DEVICES.n6210 = {
+ "name" : "Nokia 6210 Navigator",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "6210_main.jpg",
+ "orientation" : true
+}
+
+// 6220 Classic
+SUPPORTED_DEVICES.n6220 = {
+ "name" : "Nokia 6220 Classic",
+ "display" : "240x320",
+ "s_display" : "",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "6220_main.jpg",
+ "orientation" : true
+}
+
+// Nokia 6650
+SUPPORTED_DEVICES.n6650 = {
+ "name" : "Nokia 6650",
+ "display" : "240x320",
+ "s_display" : "128x160",
+ "platform" : "S60 3rd Edition, Feature Pack 2",
+ "image" : "6650-2_main.jpg",
+ "orientation" : true
+}
+
+// 5800 XpressMusic
+SUPPORTED_DEVICES.n5800 = {
+ "name" : "Nokia 5800 XpressMusic",
+ "display" : "360x640 ",
+ "s_display" : "",
+ "platform" : "S60 5th Edition",
+ "image" : "5800_main.jpg",
+ "orientation" : true
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/lib/loader.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,9 @@
+addScript("preview/script/lib/systeminfo.js");
+addScript("preview/script/lib/menu.js");
+addScript("preview/script/lib/menuItem.js");
+addScript("preview/script/lib/widget.js");
+
+// Includes a script file by writing a script tag.
+function addScript(src) {
+ document.write("<script type=\"text/javascript\" src=\"" + src + "\"></script>");
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/lib/menu.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,492 @@
+/*
+ Function : menu()
+ Argument : Void
+ Returns : Void
+ Description : Constructor Function creates a Menu object to the WINDOW
+*/
+
+function Menu()
+{
+ this.items = Array();
+ this.index = null;
+ this.isDimmed = false;
+
+ // Event triggers
+ this.onShow = null;
+ this.onRightSoftKeySelect = null;
+
+ // Flag for Menu softkeys disabled to show
+ this.is_sfk_disabled = false;
+}
+
+
+/*
+ Function : menu.append()
+ Argument : MenuItem Object
+ Returns : Void
+ Description : Function appends MenuItem to a Menu Object
+*/
+Menu.prototype.append = function(MenuItem)
+{
+ if(this.allowedTypeOf(MenuItem))
+ {
+ var i;
+ var flag = true;
+ try{
+ for(i=0; i<this.items.length; i++)
+ {
+ if(this.items[i].id == MenuItem.id)
+ {
+ flag = false;
+ break;
+ }
+ }} catch(e){ }
+ if(flag)
+ {
+ // MenuItem.parent = this;
+ this.items.push(MenuItem);
+ }
+ }
+}
+
+
+/*
+ Function : menu.remove()
+ Argument : MenuItem Object
+ Returns : Void
+ Description : Function Remove the menuItem and its children from the container options menu.
+*/
+Menu.prototype.remove = function(MenuItem)
+{
+ if(!this.allowedTypeOf(MenuItem))
+ return false;
+
+ var i;
+ var flag = false;
+ if (this.items.length) {
+ for (i = 0; i < this.items.length; i++) {
+ if (this.items[i].id == MenuItem.id) {
+ flag = true;
+ break;
+ }
+ }
+ }
+ if(flag)
+ {
+ this.items.splice(i, 1);
+ }
+}
+
+/*
+ Function : menu.clear()
+ Argument : Void
+ Returns : Void
+ Description : Clears (deletes) all the menu items in the menupane.
+*/
+Menu.prototype.clear = function()
+{
+ try
+ {
+ this.items.splice(0, this.items.length);
+ }catch(e){}
+}
+
+
+/*
+ Function : Menu.getMenuItemById(id)
+ Argument : Integer
+ Returns : MenuItem Object
+ Description : Function get the MenuItem Object with the reference of id
+*/
+Menu.prototype.getMenuItemById = function(id)
+{
+ var menuItemRef = menuItemExhistsById(this, id, 0);
+ if(this.allowedTypeOf(menuItemRef))
+ return menuItemRef;
+ else
+ return undefined;
+}
+
+
+/*
+ Function : Menu.getMenuItemByName(name)
+ Argument : String
+ Returns : MenuItem Object
+ Description : Function get the MenuItem Object with the reference of String name
+*/
+Menu.prototype.getMenuItemByName = function(name)
+{
+ var menuItemRef = menuItemExhistsById(this, name, 1);
+
+// if(menuItemRef !=null)
+ if(this.allowedTypeOf(menuItemRef))
+ return menuItemRef;
+ else
+ return undefined;
+}
+
+/*
+ Function : Menu.setRightSoftkeyLabel()
+ Argument : String, Function
+ Returns : Void
+ Description : Set the label of the right soft key to str. This enables the default text
+ to be changed from �exit� and a new function assigned by setting a callbackfunction
+*/
+Menu.prototype.setRightSoftkeyLabel = function(label, callbackfunction)
+{
+ window.menu = this;
+
+ try
+ {
+ var rightSoftKey = childToParent_Reference.$('rightSoftKey');
+ if(typeof(callbackfunction) == 'function')
+ {
+ rightSoftKey.innerHTML = label;
+
+ this.onRightSoftKeySelect = callbackfunction;
+ rightSoftKey.setAttribute('onClick', 'javascript:Emulator.triggerChildRSK();');
+ }
+ else
+ {
+ rightSoftKey.innerHTML = "Cancel";
+ this.onRightSoftKeySelect = null;
+ rightSoftKey.setAttribute('onClick', 'javascript:Emulator.triggerChildRSK();');
+ }
+ }catch(e){ }
+}
+
+/*
+ Function : Menu.showSoftkeys()
+ Argument : Void
+ Returns : Void
+ Description : Makes the softkeys visible. By default the softkeys are not visible
+
+*/
+Menu.prototype.showSoftkeys = function()
+{
+ /*
+ * Shows showSoftkeys
+ */
+ this.is_sfk_disabled = false;
+ childToParent_Reference.Emulator.showDeviceSoftKeys();
+}
+
+/*
+ Function : Menu.hideSoftkeys()
+ Argument : Void
+ Returns : Void
+ Description : Makes the softkeys invisible. By default the softkeys are not visible.
+
+*/
+Menu.prototype.hideSoftkeys = function()
+{
+ /*
+ * Hide showSoftkeys
+ */
+ this.is_sfk_disabled = true;
+ childToParent_Reference.Emulator.hideDeviceSoftKeys();
+}
+
+
+/*
+ *
+ * ----------------------------------------------------------------
+ * Exta Functionalities which helps to make main functions to work
+ * ----------------------------------------------------------------
+ *
+*/
+
+Menu.prototype.cancel = function()
+{
+ /*
+ * Clear menu and Exit the widget
+ */
+
+ childToParent_Reference.$('menuItemsPane').innerHTML = '';
+ childToParent_Reference.$('menuItemsPane').style.display = 'none';
+
+ if(this.is_sfk_disabled)
+ childToParent_Reference.Emulator.hideDeviceSoftKeys();
+}
+
+Menu.prototype.exit = function()
+{
+ /*
+ * Clear menu and Exit the widget
+ */
+
+ childToParent_Reference.$('menuItemsPane').innerHTML = '';
+ childToParent_Reference.$('menuItemsPane').style.display = 'none';
+
+ if(childToParent_Reference.Emulator.showSoftKeys_disabled)
+ childToParent_Reference.$('menuPane').style.display = 'none';
+
+ // call the Parent function
+ childToParent_Reference.Emulator.triggerExit();
+}
+
+
+Menu.prototype.showMenu = function(parentId)
+{
+ try{
+ var menuItemsPane = childToParent_Reference.$('menuItemsPane')
+ menuItemsPane.innerHTML = '';
+
+ var menuPane = childToParent_Reference.$('menuPane');
+ menuPane.style.display = 'block';
+
+ var ul = document.createElement('ul');
+ var ele = this;
+ if(parentId)
+ {
+ ele = menuItemExhistsById(ele, parentId, 0);
+ }
+ if(ele.items.length)
+ {
+ for(var i=0; i<ele.items.length; i++)
+ {
+ if(!ele.items[i].isDimmed){
+
+ try{
+ ul.appendChild(createMenuElement(ele.items[i]));
+ }catch(e){ }
+ }
+ }
+ if(parentId)
+ {
+ if(ele.parent)
+ ul.appendChild(createNormalMenuElement('Back', ele.parent.id));
+ else
+ ul.appendChild(createNormalMenuElement('Back', null));
+ }
+ else
+ {
+ ul.appendChild(createExitMenuElement());
+ }
+ if(ele.items.length > 1)
+ menuItemsPane.style.overflowY = 'scroll';
+ else
+ menuItemsPane.style.overflowY = 'hidden';
+ }
+ else
+ {
+ menuItemsPane.style.overflowY = 'hidden';
+ ul.appendChild(createExitMenuElement());
+ }
+ menuItemsPane.innerHTML = '<ul>'+ul.innerHTML+'</ul>';
+ /*
+ * Set the MenuKeys DIV style.top
+ */
+ childToParent_Reference.Emulator.showDeviceSoftKeys();
+ }
+ catch(e)
+ {
+ alert('showMenu: '+e);
+ }
+}
+
+Menu.prototype.triggeLeftSoftKeyEvent = function()
+{
+ if(typeof(window.menu.onShow) == 'function')
+ {
+ window.menu.onShow();
+ }
+ childToParent_Reference.$('softKeysPane').style.display = 'block';
+ this.showMenu();
+}
+
+Menu.prototype.triggeEvent = function(MenuItemId)
+{
+ try{
+ var menuItemRef = menuItemExhistsById(this, MenuItemId, 0);
+ if(menuItemRef != null)
+ {
+ if(typeof menuItemRef.onSelect == 'function')
+ menuItemRef.onSelect(MenuItemId);
+
+ if(menuItemRef.items.length)
+ this.showMenu(MenuItemId);
+ else
+ this.cancel();
+ }
+ }
+ catch(e)
+ {
+ alert('triggeEvent: '+MenuItemId+' >> '+e);
+ }
+}
+
+Menu.prototype.hasChild = function(parentId)
+{
+ for(var i=0; i<this.items.length; i++)
+ {
+ if(this.items[i].parentId == parentId)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+Menu.prototype.allowedTypeOf = function(MenuItem)
+{
+ try
+ {
+ if( (typeof(MenuItem) == 'object') && (MenuItem.type == 'MenuItem'))
+ return true;
+ }
+ catch(e)
+ {
+ return false;
+ }
+}
+
+function widgetMenuReferenceShowMenu_NOKIA(parentId)
+{
+ window.menu.showMenu(parentId);
+}
+
+function widgetTriggeMenuEvent_NOKIA(MenuItemId)
+{
+ alert(MenuItemId);
+ window.menu.triggeEvent(MenuItemId);
+}
+
+/*
+ MenuItemExhists??
+*/
+function menuItemExhistsById(menuReference, value, argumentType)
+{
+ var i;
+ var flag = null;
+
+ for(i=0; i<menuReference.items.length; i++)
+ {
+ if(!argumentType)
+ {
+ if(menuReference.items[i].id == value)
+ {
+ flag = true;
+ break;
+ }
+ }
+ else
+ {
+ if(menuReference.items[i].name == value)
+ {
+ flag = true;
+ break;
+ }
+ }
+
+ if(menuReference.items[i].items != undefined && menuReference.items[i].items.length)
+ {
+ var temp = menuItemExhistsById(menuReference.items[i], value, argumentType);
+ if(temp)
+ return temp;
+ }
+ }
+ if(flag)
+ {
+ // crate a package and send it
+ menuReference.items[i].index = i;
+ return menuReference.items[i];
+ }
+ else
+ return null;
+}
+
+function createMenuElement(MenuItem)
+{
+ var listitem = document.createElement('li');
+ listitem.id = MenuItem.id;
+/* if(MenuItem.onSelect)
+ {
+ listitem.setAttribute('onClick', 'javascript:widgetTriggeMenuEvent_NOKIA('+MenuItem.id+');');
+ }
+*/ listitem.setAttribute('onClick', 'javascript:Emulator.triggerMenuEvent('+MenuItem.id+');');
+
+ var anchor = document.createElement('a');
+ anchor.id = 'subMenuItem_'+MenuItem.id;
+ anchor.innerHTML = MenuItem.name;
+ if(MenuItem.items.length)
+ {
+ listitem.className = 'subMenuItem';
+ anchor.setAttribute('href', 'javascript:Emulator.triggerMenuShow('+MenuItem.id+');');
+ }
+ listitem.appendChild(anchor);
+ return (listitem);
+}
+
+function createNormalMenuElement(MenuTitle, index)
+{
+ var listitem = document.createElement('li');
+
+ var anchor = document.createElement('a');
+ anchor.id = 'subMenuItem_BACK';
+ anchor.innerHTML = MenuTitle;
+
+ if(MenuTitle == 'Application Switcher')
+ {
+ listitem.className = 's60AppToggle';
+ anchor.setAttribute('href', 'javascript:window.menu.cancel();');
+ }
+ else if (MenuTitle == 'Back') {
+ listitem.className = 'exitOrBackBtn';
+ anchor.setAttribute('href', 'javascript:Emulator.triggerMenuShow(' + index + ');');
+ }
+ else
+ anchor.setAttribute('href', 'javascript:Emulator.triggerMenuShow(' + index + ');');
+
+ listitem.appendChild(anchor);
+ return (listitem);
+}
+
+function createExitMenuElement()
+{
+ var listitem = document.createElement('li');
+ listitem.className = 'exitOrBackBtn';
+ var anchor = document.createElement('a');
+ anchor.id = 'subMenuItem_EXIT';
+ anchor.innerHTML = 'Exit';
+ anchor.setAttribute('href', 'javascript:Emulator.triggerMenuExit();');
+
+ listitem.appendChild(anchor);
+ return (listitem);
+}
+
+function triggeRSK()
+{
+ try {
+ if (window.menu) {
+ if (childToParent_Reference.$('softKeysPane').style.display != 'none') {
+ if (window.menu.onRightSoftKeySelect != null) {
+ window.menu.onRightSoftKeySelect();
+ window.menu.cancel();
+ }
+ else {
+ window.menu.cancel();
+ }
+ }
+ }
+ }catch(e)
+ {
+ alert(e);
+ }
+}
+
+function triggeLSK()
+{
+ if(window.menu)
+ {
+ window.menu.showMenu();
+ if(typeof(window.menu.onShow) == 'function')
+ {
+ if(window.menu.onShow)
+ {
+ window.menu.onShow();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/lib/menuItem.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,91 @@
+/*
+ Function : MenuItem()
+ Argument : Void
+ Returns : Void
+ Description : Constructor Function creates a Menu object to the WINDOW
+*/
+
+function MenuItem(name, id)
+{
+ this.id = id;
+ this.name = name;
+ this.isDimmed = false;
+
+ this.items = Array();
+ this.index = null;
+ this.parent = null;
+ this.type = 'MenuItem';
+
+
+ // Event triggers
+ this.onSelect = null;
+}
+
+
+/*
+ Function : MenuItem.append(MenuItem)
+ Argument : Menu Object
+ Returns : Void
+ Description : Function appends childMenuItem to a MenuItem
+*/
+MenuItem.prototype.append = function(childMenuItem)
+{
+ if( (childMenuItem != null) && (childMenuItem.type == 'MenuItem'))
+ {
+ childMenuItem.parent = this;
+ this.items.push(childMenuItem);
+ }
+}
+
+
+/*
+ Function : MenuItem.remove()
+ Argument : Menu Object
+ Returns : Void
+ Description : Function Removes childMenuItem and its children from the parent menu item.
+*/
+MenuItem.prototype.remove = function(childMenuItem)
+{
+ if((childMenuItem != null) && (childMenuItem.type == 'MenuItem'))
+ {
+ var i = this.search(childMenuItem);
+ if(i > -1)
+ this.items.splice(i, 1);
+ }
+}
+
+/*
+ Function : MenuItem.remove()
+ Argument : Menu Object
+ Returns : Void
+ Description : If flag is true the MenuItem is hidden and if flag is false the item is shown.
+*/
+MenuItem.prototype.setDimmed = function(flag)
+{
+ this.isDimmed = flag;
+}
+
+
+/*
+ Function : MenuItem.search()
+ Argument : MenuItem Object
+ Returns : Integer
+ Description : Function Replace oldMenuItem with newMenuItem
+*/
+MenuItem.prototype.search = function(MenuItem)
+{
+ var i;
+ var flag = false;
+ for(i=0; i<this.items.length; i++)
+ {
+ if(this.items[i].id == MenuItem.id)
+ {
+ flag = true;
+ break;
+ }
+ }
+ if(flag)
+ return i;
+ else
+ return -1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/lib/systeminfo.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,103 @@
+/**
+ This API is used to provide system related data.
+ It takes the sysObject as an argument that is the embeded API in the main HTML file.
+ While using this API outside mobile environment, User or developer need not to take any extara action in oprder to support SYSAPI.
+*/
+
+function systemAPI(sysObject)
+{
+ /*
+ * System Language information services
+ */
+ sysObject.language = 'EN';
+
+
+
+
+ /*
+ * Power information services
+ */
+
+ // Properties
+ sysObject.chargelevel = 5;
+ sysObject.chargerconnected = 0;
+
+ // Event triggers
+ sysObject.onchargelevel = null;
+ sysObject.onchargerconnected = null;
+
+
+
+ /*
+ * Beep tone control services
+ */
+ sysObject.beep = function(frequency, duration){ }
+
+
+
+ /*
+ * Network Information services
+ */
+
+ // value range between: {0-7}
+ sysObject.signalbars = 7;
+
+ sysObject.networkname = 'No network';
+
+ // value range between: {0-7}
+ sysObject.networkregistrationstatus = 0;
+
+
+
+ /*
+ * Display and keypad illumination information and control services
+ */
+
+ // Properties
+ sysObject.lightminintensity = 1;
+ sysObject.lightmaxintensity = 100;
+ sysObject.lightdefaultintensity = 0;
+
+ sysObject.lightinfiniteduration = 0;
+ sysObject.lightmaxduration = 1;
+ sysObject.lightdefaultcycletime = 0;
+
+ sysObject.lighttargetprimarydisplayandkeyboard = 0x3;
+ sysObject.lighttargetsystem = 1;
+
+ // functions
+ sysObject.lighton = function(lighttarget, duration, intensity, fadein){ }
+ sysObject.lightblink = function(lighttarget, duration, onduration, offduration, intensity){ }
+ sysObject.lightoff = function(lighttarget, duration, fadeout){ }
+
+
+
+ /*
+ * Vibration information and control services
+ */
+ sysObject.vibraminintensity = 1;
+ sysObject.vibramaxintensity = 10;
+ sysObject.vibramaxduration = 100;
+
+ // Vibration setting in the user profile is off.
+ sysObject.vibrasettings = 2;
+
+ sysObject.startvibra = function(duration, intensity){ }
+
+ sysObject.stopvibra = function(){ }
+
+
+
+
+ /*
+ * Memory and file system information services
+ */
+ sysObject.totalram = 32;
+ sysObject.freeram = 10;
+ sysObject.drivelist = 'C';
+
+ sysObject.drivesize = function(drive){ return 64; }
+
+ sysObject.drivefree = function(drive){ return 32; }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/preview/script/lib/widget.js Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,388 @@
+/**
+ * Widget object constructor
+ * @param {void}
+ * widget()
+ * @return {void}
+ */
+function Widget()
+{
+ // widget identifier, dummy value
+ this.identifier = 14021981;
+ this.isrotationsupported = true;
+
+ // widget event triggers
+ this.onshow = null;
+ this.onhide = null;
+
+ /*
+ * Custom extra functionalities to support
+ */
+ this.path = document.location.pathname;
+ this.sysAPI = null;
+ this.onload = null;
+ this.opacity = 50;
+ this.interval = 20;
+ this.isFront = false;
+ this.preferenceArray = new Array();
+ this.preferenceKey = 0;
+}
+
+
+/**
+ * Launches the browser with the specified url
+ * @param {String} url
+ * openURL()
+ * @return {Void}
+ */
+Widget.prototype.openURL = function(url)
+{
+ if (url) {
+ window.open(url ,"New Widget Window",'height=200 width=250');
+ }
+}
+
+
+/**
+ * Returns previously stored preference associated with the specified key
+ * @param {String} Key preference value to be fetch
+ * preferenceForKey()
+ * @return {String} Value
+ */
+Widget.prototype.preferenceForKey = function(key){
+ var name = "Nokia_WRT#" + this.path + "#" + key;
+ var result = readCookie(document, name);
+ return result;
+}
+
+
+/**
+ * Stores the key associated with the specified preference
+ * @param {String} Preference value to be stored
+ * @param {String} Key Preference value associated to
+ * setPreferenceForKey()
+ * @return {Void}
+ */
+Widget.prototype.setPreferenceForKey = function(preference, key)
+{
+ var value;
+ //Specifying null for the preference parameter removes the specified key from the preferences
+ if(key == null){
+ if(this.preferenceKey>0){
+ this.preferenceKey--;
+ }
+ //delete from cookies
+ }
+ value = "Nokia_WRT#"+this.path+"#"+key;
+ this.preferenceArray[this.preferenceKey] = value;
+
+ createCookie(document,value,preference,240000);
+ this.preferenceKey++;
+
+ //save cookie for cookies
+ updateMainCookie(document);
+}
+
+
+
+/**
+ * Toggle between Tabbed navigation mode or Cursor mode
+ * @param {Boolean} Value
+ * setNavigationEnabled()
+ * @return {Void}
+ */
+Widget.prototype.setNavigationEnabled = function(bool)
+{
+ //This function can not be used on preview browser
+}
+
+
+
+/**
+ * Open S0-Application identified by UID along with the specified params
+ * @param {Integer} Uid hexadecimal value to a specified application
+ * @param {String} Value
+ * openApplication()
+ * @return {Void}
+ */
+Widget.prototype.openApplication = function(Uid, param)
+{
+ alert("openApplication function won't be simulated in this application");
+}
+
+
+
+/**
+ * Prepares the Widget.to do transition to specified transitionState
+ * @param {String} Value Transition state
+ * prepareForTransition()
+ * @return {Void}
+ */
+Widget.prototype.prepareForTransition = function(transitionState)
+{
+ this.isFront = ("" + transitionState).toLowerCase() != "toback";
+ window.document.getElementsByTagName("body")[0].style.opacity = "0.3";
+}
+
+
+
+
+/**
+ * Does the animation to make the transition between the specified transitionState
+ * @param {Void}
+ * performTransition()
+ * @return {Void}
+ */
+Widget.prototype.performTransition = function()
+{
+ var _self = this;
+ this.opacity = 0;
+ this.interval = window.setInterval(function() {
+ _self.opacity += 0.2;
+ if (_self.opacity > 1) {
+ _self.opacity = 1;
+ }
+ window.document.getElementsByTagName("body")[0].style.opacity = _self.opacity + "";
+ if (_self.opacity >= 1) {
+ window.clearInterval(_self.interval);
+ window.document.getElementsByTagName("body")[0].style.opacity = "1";
+ }
+ //do nothing
+ }, 50);
+ //do nothing
+}
+
+
+
+
+
+/**
+ * Set the preferred screen orientation to landscape.
+ * The display will flip if the phone display orientation
+ * is portrait and the phone supports landscape mode.
+ * @param {Void}
+ * setDisplayLandscape()
+ * @return {Void}
+ */
+Widget.prototype.setDisplayLandscape = function(){
+ try
+ {
+ if (this.isrotationsupported && childToParent_Reference.Emulator.orientation_mode != 'landscape')
+ {
+ childToParent_Reference.Emulator.changeOrientation(childToParent_Reference.$('DisplayOrientation'));
+ }
+ }
+ catch (e) {}
+}
+
+
+
+
+/**
+ * Set the preferred screen orientation to portrait.
+ * The display will flip if the phone display orientation
+ * is landscape and the phone supports portrait mode.
+ * @param {Void}
+ * setDisplayPortrait()
+ * @return {Void}
+ */
+Widget.prototype.setDisplayPortrait = function()
+{
+ try
+ {
+ if (this.isrotationsupported && childToParent_Reference.Emulator.orientation_mode != 'portrait')
+ {
+ childToParent_Reference.Emulator.changeOrientation(childToParent_Reference.$('DisplayOrientation'));
+ }
+ }
+ catch (e) {}
+}
+
+/**
+ * Allows the definition of a function to be called
+ * when a Widget.is displayed
+ * @param {Void}
+ * onshow()
+ * @return {Void}
+ */
+Widget.prototype.onshow = function()
+{
+ // to be implemented
+}
+
+
+
+
+/**
+ * Allows the definition of a function to be called
+ * when a Widget.sent into the background (hidden)
+ * @param {Void}
+ * onhide()
+ * @return {Void}
+ */
+Widget.prototype.onhide = function()
+{
+ // to be implemented
+}
+
+
+
+/**
+ * This function returns the System API if sysinfo is included in document embed
+ */
+Widget.prototype.enableSystemApi = function()
+{
+
+ // Identify, and Attach System-Info-Object properties
+ try
+ {
+ var parentIframeRef = window.parent.frames[0];
+ if(parentIframeRef)
+ {
+ if (parentIframeRef.document.embeds.length > 0) {
+ for (var i = 0; i < parentIframeRef.document.embeds.length; i++)
+ {
+ //match the system Info API embed tag
+ if (parentIframeRef.document.embeds[i].type == 'application/x-systeminfo-widget')
+ {
+ new systemAPI(parentIframeRef.document.embeds[i]);
+ widget.sysAPI = parentIframeRef.document.embeds[i];
+ }
+ }
+ }
+ }
+ }
+ catch (e) {
+ alert('Error in attachSysInfo: ' + e);
+ }
+
+ // Attach menu object to window
+ window.menu = new Menu();
+
+ // Attach window reference to the Parent Window
+ window.parent.Emulator.parentToChild_Reference = window;
+
+ // add event listener to window.focus
+ window.onfocus = function(){ menu.cancel(); }
+
+ // add event listener to window.focus
+ window.onunload = function()
+ {
+ try
+ {
+ // Trigger Callback of Widget.onHide function
+ if(typeof(widget.onhide) == 'function')
+ {
+ widget.onhide();
+ }
+ }
+ catch(e){ errorLog('widget.onhide: '+e.description, 0); }
+ }
+
+
+ /*
+ * Used as a bridge between, Child widget & Parent window
+ */
+ window.childToParent_Reference = window.parent;
+
+}
+
+/*
+ * support functions for widget object
+ */
+
+/**
+ * This function stores cookie for all the cookies
+ * to help finding cookies of the same document while clearing preferences
+ * @param doucment -- Document object
+ */
+function updateMainCookie(doucment){
+ var temp="";
+ name = "Nokia_WRT#"+widget.path;
+ for (var k = 0; k<widget.preferenceArray.length; k++){
+ temp = temp+"|"+widget.preferenceArray[k];
+ }
+ createCookie(document,name,temp,24000);
+}
+
+/**
+ * This function creates cookie for the setPreferenceForKey function in order to save key-pref persistently
+ *
+ * @param document -- Document object
+ * @param name -- Name of the cookie
+ * @param value -- value for the name cookie
+ * @param days -- expire
+ *
+ */
+
+function createCookie(document,name,value,days) {
+ if (days) {
+ var date = new Date();
+ date.setTime(date.getTime()+(days*24*60*60*1000));
+ var expires = "; expires="+date.toGMTString();
+ }
+ else var expires = "";
+ document.cookie = name+"="+value+expires+"; path=/"
+}
+
+/**
+ * This function retrieves back the values from the cookies
+ * @param document
+ * @param name
+ * @return
+ */
+function readCookie(document , name) {
+ var nameEQ = name + "=";
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
+ if (c.indexOf(nameEQ) == 0) {
+ return c.substring(nameEQ.length,c.length);
+ }
+ }
+ return undefined;
+}
+
+
+/*
+ * /////////////////////////////////////////////////////////////////////////////////////
+ * ////////////////////////////// Ends here //////////////////////////////////
+ * /////////////////////////////////////////////////////////////////////////////////////
+ */
+
+function errorLog(str, flag)
+{
+// alert(str);
+}
+
+/*
+ * by John Resig
+ * @reference: http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
+ */
+function addEvent( obj, type, fn ){
+ if (obj.addEventListener){
+ obj.addEventListener( type, fn, false );
+ }
+ else if (obj.attachEvent){
+ obj["e"+type+fn] = fn;
+ obj[type+fn] = function(){ obj["e"+type+fn]( window.event ); }
+ obj.attachEvent( "on"+type, obj[type+fn] );
+ }
+}
+
+/*
+ * Create a new Widget Object when DOM ready
+ *
+*/
+try
+{
+ // attach widget object to window
+ var widget = new Widget();
+
+ // attach the System-Info api specific functionality
+ addEvent(window, 'load', widget.enableSystemApi);
+}
+catch (e)
+{
+ alert('Exception: Widget object creation');
+}
Binary file Symbian.org/right.gif has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/style.css Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,53 @@
+/* Feed item date */
+.FeedItemDate {
+ font-style: italic;
+}
+
+/* Feed item text */
+.FeedItemDescription {
+ padding: 4px 0px;
+}
+
+/* Feed item links */
+.FeedItemLink {
+ font-weight: bold;
+}
+
+/* Anchor tags in the context of a feed item link */
+.FeedItemLink a {
+ text-decoration: underline;
+ font-weight: bold;
+ color: rgb(0,0,0);
+}
+
+/* Focused anchor tags */
+.FeedItemLink a:focus {
+ background: rgb(253,200,47);
+ color: rgb(0,0,0);
+}
+
+table.bugzilla {
+ font: normal 12px Arial, sans-serif;
+ border-width: thin thin thin thin;
+ border-spacing: 0px;
+ border-style: none none none none;
+ border-color: black black black black;
+ border-collapse: collapse;
+ background-color: white;
+}
+table.bugzilla th {
+ font: normal 12px Arial, sans-serif;
+ border-width: thin thin thin thin;
+ padding: 1px 1px 1px 1px;
+ border-style: inset inset inset inset;
+ border-color: gray gray gray gray;
+ background-color: white;
+}
+table.bugzilla td {
+ font: normal 12px Arial, sans-serif;
+ border-width: thin thin thin thin;
+ padding: 1px 1px 1px 1px;
+ border-style: inset inset inset inset;
+ border-color: gray gray gray gray;
+ background-color: white;
+}
Binary file Symbian.org/titlebar.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/wrt_preview_frame.html Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Nokia WRT Preview</title>
+<link href="preview/css/style.css" rel="stylesheet" type="text/css" />
+<script language="JavaScript" src="preview/script/device.js"></script>
+<script language="JavaScript" src="preview/script/build.js"></script>
+<link href="preview/css/menu.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="Toolbar">
+ <div id="DeviceSettings">
+ <table cellpadding="0" cellspacing="0">
+ <tr valign="middle">
+ <td width="230" align="left" valign="top"><img src="preview/images/select-device-text.png" alt="Select Device" width="110" height="18" hspace="15" /><br />
+ <select name="deviceResolution" size="5" id="deviceResolution">
+ </select></td>
+ <td width="87" align="center"><img src="preview/images/device/5320_main.jpg" alt="Device" name="ModelImage" width="57" height="150" id="ModelImage" /></td>
+ </tr><tr>
+ <td colspan="2"> <p>Model: <br />
+ <strong id="ModelName">Nokia 5320 XpressMusic</strong></p>
+ <p>Resolution: <br />
+ <strong id="ModelResolution">240 x 320 pixels</strong></p> </td>
+ </tr><tr>
+ <td colspan="2"><p>Developer Platform: <br />
+ <strong id="ModelPlatform">S60 3rd Edition, Feature Pack 2</strong></p>
+ <p>Display Orientation:<br />
+ <label>
+ <input name="DisplayOrientation" type="radio" id="DisplayOrientation_portrait" value="portrait" checked="checked"/>
+ Portrait</label>
+ <label>
+ <input type="radio" name="DisplayOrientation" value="landscape" id="DisplayOrientation_landscape" />
+ Landscape<br />
+ </label>
+ </p></td>
+ </tr>
+ </table>
+</div>
+ <div class="down" id="pullDown"></div>
+ </div>
+<div id="WrapperDiv">
+<div id="device">
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <div id="display">
+ <div id="displayLeft">
+ <div id="iframePreviewWindow">
+ <iframe src="wrt_preview_main.html" frameborder="no" width="100%" id="widgetIframeWindow"></iframe>
+ <div id="menuPane">
+ <div id="menuItemsPane">
+ </div>
+ <div id="softKeysPane">
+ <table width="100%" border="0" cellspacing="2" cellpadding="2">
+ <tr>
+ <td><span id="leftSoftKey">Options</span></td>
+ <td align="right"><span id="rightSoftKey">Cancel</span></td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</td>
+ </tr>
+ <tr>
+ <td>
+ <div id="softKeys">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td width="46"><a id="leftSoftKeyImg"><img src="preview/images/device-left-softkey.png" width="103" height="46" border="0" /></a></td>
+ <td background="preview/images/device-bottom.png"> </td>
+ <td width="46"><a id="rightSoftKeyImg"><img src="preview/images/device-right-softkey.png" width="103" height="46" border="0" /></a></td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</div>
+</div>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian.org/wrt_preview_main.html Fri Jun 05 16:18:05 2009 +0100
@@ -0,0 +1,23 @@
+<html>
+ <head>
+ <script language="JavaScript" type="text/javascript" src="preview/script/lib/loader.js"></script>
+
+ <title>Symbian.org</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <script type="text/javascript" src="WRTKit/WRTKit.js"></script>
+ <script type="text/javascript" src="FeedUpdateBroker.js"></script>
+ <script type="text/javascript" src="FeedPresentation.js"></script>
+ <script type="text/javascript" src="Forums.js"></script>
+ <script type="text/javascript" src="Login.js"></script>
+ <script type="text/javascript" src="Bugzilla.js"></script>
+ <script type="text/javascript" src="ForumPostForm.js"></script>
+ <script type="text/javascript" src="RssReader.js"></script>
+ <script type="text/javascript" src="Main.js"></script>
+ <style type="text/css">
+ @import url("style.css");
+ </style>
+ <META NAME="Generator" CONTENT="Nokia WRT plug-in for Aptana Studio 1.0.0.36" />
+ </head>
+ <body onload="init()">
+ </body>
+</html>
\ No newline at end of file