# HG changeset patch # User ivanl # Date 1244215085 -3600 # Node ID 54498df70f5dff1e6e5389e8238560c180f7fce4 Adding Symbian.org Widget 1.0rc3 source diff -r 000000000000 -r 54498df70f5d Symbian.org/.project --- /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 @@ + + + Symbian.org + + + + + + com.nokia.wrt.widgetPreviewBuilder + + + + + + com.nokia.wrt.WidgetProjectNature + com.aptana.ide.project.nature.web + + diff -r 000000000000 -r 54498df70f5d Symbian.org/Bugzilla.js --- /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 += "
"; + var ld_nodes = node.childNodes; + for ( var tmp = 0 ; tmp < ld_nodes.length ; tmp++ ) { + longdesc += ""; + } + longdesc += "
" + + getTextOfNode(ld_nodes[tmp]) + "
"; + } else if (node.nodeName == "assigned_to" ) { + assignedToName = getTextOfNode(node); + } + } + node = node.nextSibling; + } + // format the description + var description = ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += ""; + description += "
Reported:" + "" + creationTime + "
Product:" + "" + product + "
Component:" + "" + component + "
Classification:" + "" + classification + "
Operating system:" + "" + op_sys + "
Status:" + "" + bug_status + "
Priority:" + "" + priority + "
Severity:" + "" + severity + "
Version:" + "" + version + "
Platform:" + "" + platform + "
Reported by:" + "" + author + "
Assigned to:" + "" + assignedToName + "
Target milestone:" + "" + target_milestone + "
File location:" + "" + bug_file_loc + "
"; + + description += ""; + description += ""; + description += ""; + description += "
Description:" + "
" + longdesc + "
"; + + description += ""; + description += ""; + description += ""; + description += "
Solution details:" + "
" + solutionDetails + "
"; + + 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" }; + } +} + diff -r 000000000000 -r 54498df70f5d Symbian.org/FeedPresentation.js --- /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 += "
" ; + if ( item.author != null ) { + buf += item.author + ", "; + } + buf += item.date + "
"; + } + + // item description + if (item.description != null) { + buf += "
" + item.description + "
"; + } + + if (item.url != null) { + // blogs + buf += "
"; +// buf += ""; + buf += ""; + buf += "Read more..."; + buf += ""; + buf += "
"; + } + + 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); + } +} + + diff -r 000000000000 -r 54498df70f5d Symbian.org/FeedUpdateBroker.js --- /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(); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/ForumPostForm.js --- /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); +// } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/Forums.js --- /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 += "
" ; + if ( item.username != null ) { + buf += item.username + ", "; + } + buf += date + "
"; + } + + // item description + if (item.pagetext != null) { + var text = bbcode2html(item.pagetext); + text = text.replace(/\r\n/g, "
"); + buf += "
" + text + "
"; + buf += "
"; + buf += ""; + buf += "Reply to this post" + buf += "
"; + } + + 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; +} + + + diff -r 000000000000 -r 54498df70f5d Symbian.org/Icon.png Binary file Symbian.org/Icon.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/Info.plist --- /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 @@ + + + + + DisplayName + Symbian.org + Identifier + org.symbian.developer.widget + Version + 1.0 + MainHTML + index.html + AllowNetworkAccess + + + \ No newline at end of file diff -r 000000000000 -r 54498df70f5d Symbian.org/Login.js --- /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(); + } + } +} + diff -r 000000000000 -r 54498df70f5d Symbian.org/Main.js --- /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 = "Symbian.org "+myversion+"
" + + "Symbian.org WRT Widget is a Web Runtime application which allows mobile " + + "access to Symbian Foundation Forums, Blog, Wiki and Bugzilla.
" + + "For more information and updates check

" + + "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, ""); + + // 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 "" + + "
" + + "

"+ caption +"

" + + "
"; +} diff -r 000000000000 -r 54498df70f5d Symbian.org/RssReader.js --- /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!
(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); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/CheckBox.png Binary file Symbian.org/WRTKit/Resources/CheckBox.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ContentPanelFoldIcons.png Binary file Symbian.org/WRTKit/Resources/ContentPanelFoldIcons.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ControlAssemblyBackground.png Binary file Symbian.org/WRTKit/Resources/ControlAssemblyBackground.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/DocumentBackground.png Binary file Symbian.org/WRTKit/Resources/DocumentBackground.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/FormButtonCenter.png Binary file Symbian.org/WRTKit/Resources/FormButtonCenter.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/FormButtonLeft.png Binary file Symbian.org/WRTKit/Resources/FormButtonLeft.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/FormButtonRight.png Binary file Symbian.org/WRTKit/Resources/FormButtonRight.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ListViewCaptionBackground.png Binary file Symbian.org/WRTKit/Resources/ListViewCaptionBackground.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/NotificationPopupBackground.png Binary file Symbian.org/WRTKit/Resources/NotificationPopupBackground.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/NotificationPopupTypeIndicator.png Binary file Symbian.org/WRTKit/Resources/NotificationPopupTypeIndicator.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ProgressBarUnknown.gif Binary file Symbian.org/WRTKit/Resources/ProgressBarUnknown.gif has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/RadioButton.png Binary file Symbian.org/WRTKit/Resources/RadioButton.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ScrollbarThumbBottom.png Binary file Symbian.org/WRTKit/Resources/ScrollbarThumbBottom.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ScrollbarThumbMiddle.png Binary file Symbian.org/WRTKit/Resources/ScrollbarThumbMiddle.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ScrollbarThumbTop.png Binary file Symbian.org/WRTKit/Resources/ScrollbarThumbTop.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ScrollbarTrackBottom.png Binary file Symbian.org/WRTKit/Resources/ScrollbarTrackBottom.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ScrollbarTrackMiddle.png Binary file Symbian.org/WRTKit/Resources/ScrollbarTrackMiddle.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/ScrollbarTrackTop.png Binary file Symbian.org/WRTKit/Resources/ScrollbarTrackTop.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/SeparatorCenter.png Binary file Symbian.org/WRTKit/Resources/SeparatorCenter.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/SeparatorLeft.png Binary file Symbian.org/WRTKit/Resources/SeparatorLeft.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/SeparatorRight.png Binary file Symbian.org/WRTKit/Resources/SeparatorRight.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Resources/UI.css --- /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; +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/ActionControl.js --- /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)); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/Ajax.js --- /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); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/ContentPanel.js --- /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"); + +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/Control.js --- /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()"); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/FormButton.js --- /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); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/ImageLabel.js --- /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"); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/Label.js --- /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"); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/ListView.js --- /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(); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/NavigationButton.js --- /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); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/NotificationPopup.js --- /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(); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/Scrollbar.js --- /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"; +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/SelectionControl.js --- /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; +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/SelectionList.js --- /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); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/SelectionMenu.js --- /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); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/Separator.js --- /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"); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/TabView.js --- /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(); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/TextArea.js --- /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); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/TextEntryControl.js --- /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)); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/TextField.js --- /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); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/UIElement.js --- /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); + } + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/UIInit.js --- /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"]; diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/UIManager.js --- /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(); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/UI/View.js --- /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(); + } + } +} + diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/Utils/Logger.js --- /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); + } +} diff -r 000000000000 -r 54498df70f5d Symbian.org/WRTKit/WRTKit.js --- /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(""); +} + +// Includes a style sheet by writing a style tag. +function includeStyleSheet(src) { + document.write(""); +} diff -r 000000000000 -r 54498df70f5d Symbian.org/blueright.gif Binary file Symbian.org/blueright.gif has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/index.html --- /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 @@ + + + Symbian.org + + + + + + + + + + + + + + + + \ No newline at end of file diff -r 000000000000 -r 54498df70f5d Symbian.org/logo.png Binary file Symbian.org/logo.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/css/menu.css --- /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 diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/css/style.css --- /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; +} diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/arrow.png Binary file Symbian.org/preview/images/arrow.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device-bottom.png Binary file Symbian.org/preview/images/device-bottom.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device-left-softkey.png Binary file Symbian.org/preview/images/device-left-softkey.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device-left.png Binary file Symbian.org/preview/images/device-left.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device-right-softkey.png Binary file Symbian.org/preview/images/device-right-softkey.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device-right.png Binary file Symbian.org/preview/images/device-right.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/5320_main.jpg Binary file Symbian.org/preview/images/device/5320_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/5800_main.jpg Binary file Symbian.org/preview/images/device/5800_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/6210_main.jpg Binary file Symbian.org/preview/images/device/6210_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/6220_main.jpg Binary file Symbian.org/preview/images/device/6220_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/6650-2_main.jpg Binary file Symbian.org/preview/images/device/6650-2_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/N95_main.jpg Binary file Symbian.org/preview/images/device/N95_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/e51_main.jpg Binary file Symbian.org/preview/images/device/e51_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/e66_main.jpg Binary file Symbian.org/preview/images/device/e66_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/e71_main.jpg Binary file Symbian.org/preview/images/device/e71_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/e90_main.jpg Binary file Symbian.org/preview/images/device/e90_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/n78_main.jpg Binary file Symbian.org/preview/images/device/n78_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/n79_main.jpg Binary file Symbian.org/preview/images/device/n79_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/n82_main.jpg Binary file Symbian.org/preview/images/device/n82_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/n85_main.jpg Binary file Symbian.org/preview/images/device/n85_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/n95_8gb_main.jpg Binary file Symbian.org/preview/images/device/n95_8gb_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/device/n96_main.jpg Binary file Symbian.org/preview/images/device/n96_main.jpg has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/menuItemHover.png Binary file Symbian.org/preview/images/menuItemHover.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/new-pull-down-btn.png Binary file Symbian.org/preview/images/new-pull-down-btn.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/s60-tiny-icon.png Binary file Symbian.org/preview/images/s60-tiny-icon.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/select-device-text.png Binary file Symbian.org/preview/images/select-device-text.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/toolbar-bg-shadow.png Binary file Symbian.org/preview/images/toolbar-bg-shadow.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/images/top-navigation-bg.png Binary file Symbian.org/preview/images/top-navigation-bg.png has changed diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/nopreview.html --- /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 @@ + + + + + +Widget preview is not available for this file, it is not the main html file for the widget. + + diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/preview_exit.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 @@ + + + + + Preview Exit + + + +

+ You have selected the Exit option from the widget menu. To see the widget preview,
Refresh Widget view. +
+ + diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/script/build.js --- /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"); +} \ No newline at end of file diff -r 000000000000 -r 54498df70f5d Symbian.org/preview/script/lib/menu.js --- /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 1) + menuItemsPane.style.overflowY = 'scroll'; + else + menuItemsPane.style.overflowY = 'hidden'; + } + else + { + menuItemsPane.style.overflowY = 'hidden'; + ul.appendChild(createExitMenuElement()); + } + menuItemsPane.innerHTML = '
    '+ul.innerHTML+'
'; + /* + * 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 -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; i0){ + 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 + + + +Nokia WRT Preview + + + + + + +
+
+ + + + + + + + + +
Select Device
+
Device

Model:
+ Nokia 5320 XpressMusic

+

Resolution:
+ 240 x 320 pixels

Developer Platform:
+ S60 3rd Edition, Feature Pack 2

+

Display Orientation:
+ + +

+
+
+
+
+
+ + + + + + + +
+
+
+
+ + +
+
+
+
+
+ + + + + + +
 
+
+
+
+
+ + diff -r 000000000000 -r 54498df70f5d Symbian.org/wrt_preview_main.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 @@ + + + + + Symbian.org + + + + + + + + + + + + + + + + \ No newline at end of file