<moblet default="splashScreen" name="mStocks" icon="images/mjxlogo_32x32.png" onError="errorHandler(event)">
<style src="mStocks.mcss"/>
<resource url="images/loading_animation.gif" persist="true"/>
<resource url="images/yahoo_finance.png" persist="true"/>
<resource url="images/house.png" persist="true"/>
<resource url="images/feed.png" persist="true"/>
<resource url="images/chart_bar.png" persist="true"/>
<resource url="images/text_list_bullets.png" persist="true"/>
<script><![CDATA[
var detail; // Stock detail
var news; // Stock news
var quotes = null; // Stock quotes
var currentSymbol; // Current stock symbol active
var currentScreen; // The current screen displayed
var resetScreen = true; // Force rebuild of screen
var resetNewsScreen; // Force rebuild of the news screen
var quoteList; // Quote list entered in rightmost tab (user configured)
var msg; // Messages displayed to user
var loadingMsg; // Message when loading data
// URL for information
// var quotesURL = "http://wu.apple.com/fq/applewidgets/quote.asp?key=tHisIsApplewidgeTs&symbols=";
var quotesURL = "http://finance.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgnprj1v&s=";
var newsURL = "http://finance.yahoo.com/rss/headline?s=";
var chartURL = "http://www.google.com/pfetch/dchart?s=";
// Default symbols
var defaultSymbols = "AAPL GOOG YHOO CSCO CPT DOW LBC";
var symbolidx = 0;
var lasttradeidx = 1;
var changeidx = 4;
var openidx = 5;
var companynameidx = 8;
var prevtradeidx = 9;
var ratioidx = 10;
var capidx = 11;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Save stock symbols on the device
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (!Cache.symbols)
{
Cache.symbols = defaultSymbols;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Set style sheet class for stock details
* (red == stock down green == stock up)
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function getChangeClass()
{
var myClass = "greenDetail";
var value = detail[changeidx];
if (value.indexOf("-") > -1)
{
myClass = "redDetail";
}
return myClass;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Download quotes
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function getQuotes(refresh)
{
// If a data refresh is needed, so progress
if (refresh)
{
resetScreen = true; // Force screen rebuild
loadingMsg = "Requesting stock quotes...";
show(loadingScreen, 1); // Show progress
}
downloadQuotes(); // Download the stock details
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Set quotes from the csv
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function setQuotes(quoteString)
{
var newQuotes = new Array();
var csvLines = quoteString.split("\n");
for (line in csvLines)
{
var values = line.split(",");
for (i=0; i < values.length; i++)
{
var start = 0;
var end = values[i].length;
if (values[i].charAt(0) == "\"")
{
start = 1;
}
if (values[i].charAt(values[i].length - 1) == "\"")
{
end = values[i].length - 1;
}
values[i] = values[i].substring(start, end);
}
newQuotes.push(values);
}
return newQuotes;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Get detail (high, low, chart, etc)
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function getDetails(symbol, refresh)
{
// If user has selected a different stock from the main tab
// or if the user has requested that the main tab be refreshed
if (currentSymbol != symbol || refresh == true)
{
currentSymbol = symbol; // Set new current symbol
loadingMsg = "Requesting " + currentSymbol + " data...";
show(loadingScreen, 1); // Show progress
resetScreen = true; // Force screen rebuild
resetNewsScreen = true; // Force news screen rebuild
downloadDetails(); // Download stock details
downloadNews(); // Download Rss news as well
}
else
displayScreen(); // No changes, simply display screen
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Get news (Rss tab)
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function refreshNews()
{
// This method will only be called if the news screen
// was requested to be refreshed
loadingMsg = "Requesting " + currentSymbol + " news...";
show(loadingScreen, 1); // Show progress
resetScreen = true; // Force screen rebuild
downloadNews(); // Download news
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Update the display
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function displayScreen()
{
// The news screen info is downloaded the same time
// as the detail screen info, so a special check is
// needed to know when to rebuild the news screen
// when something changes on the details screen
if (currentScreen == newsScreen && resetNewsScreen)
{
currentScreen.reset(); // Force screen rebuild
resetNewsScreen = false; // Reset news screen flag
}
else
{
// If reset/refresh is requested (on any screen)
if (resetScreen)
{
currentScreen.reset(); // Force screen rebuild
resetScreen = false; // Reset flag
}
}
hide(loadingScreen); // Hide the loading screen
show(currentScreen); // Show screen
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Retry a failed data request
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function retryDataRequest()
{
// Depending on which screen was active when data reqeust failed...
if (currentScreen == mainScreen)
getQuotes(true);
else
getDetails(currentSymbol, true);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Moblet error handler
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function errorHandler(e)
{
msg = e.label;
show(errorScreen, 1);
}
]]></script>
<prototype name="tabrow" layout="none" extends="Box" width="100%">
<attribute name="active">
this.children[0].children[this.active].class = "onstate";
</attribute>
<box layout="horizontal" width="100%" y="7">
<imagebox class="offstate" height="100%" width="100%" halign="center"
layout="vertical" valign="center" url="images/house.png"/>
<imagebox class="offstate" height="100%" width="100%" halign="center"
layout="vertical" valign="center" url="images/chart_bar.png"/>
<imagebox class="offstate" height="100%" width="100%" halign="center"
layout="vertical" valign="center" url="images/feed.png"/>
<imagebox class="offstate" height="100%" width="100%" halign="center"
layout="vertical" valign="center" url="images/text_list_bullets.png"/>
</box>
</prototype>
<prototype name="quote" extends="Box" layout="horizontal" width="100%" focusable="true">
<attribute name="symbol">this.children[0].value = this.symbol;</attribute>
<attribute name="lasttrade">this.children[1].value = this.lasttrade;</attribute>
<attribute name="change">
// Set color based on stock up/down
if (this.change.indexOf("-") < 0)
this.children[2].class = 'green';
else
this.children[2].class = 'red';
this.children[2].value = this.change;
</attribute>
<attribute name="position">
// Alternate current row color
if (this.position % 2)
this.class = "even";
else
this.class = "odd";
</attribute>
<method name="onClick">
// On click, move to next (details screen)
currentScreen = detailsScreen;
getDetails(this.symbol, false);
</method>
<textbox class="symbol" width="100%"/>
<textbox class="lasttrade" width="100%" halign="right"/>
<textbox class="green" width="100%" halign="right"/>
</prototype>
<prototype name="companyname" layout="vertical" extends="TextBox" width="100%"
halign="center" valign="center"/>
<prototype name="stockdetail" layout="vertical" extends="Box" width="100%">
<gridbox cols="4" rows="3" height="100%" width="100%" layout="horizontal" valign="top">
<textbox width="100%" class="quoteslabel" maxLines="1">Last:</textbox>
<textbox width="100%" class="quotesvalue" maxLines="1">bind{detail[lasttradeidx]}</textbox>
<textbox width="100%" class="quoteslabel" maxLines="1">Change:</textbox>
<textbox width="100%" class="bind{getChangeClass()}" maxLines="1">bind{detail[changeidx]}</textbox>
<textbox width="100%" class="quoteslabel" maxLines="1">Open:</textbox>
<textbox width="100%" class="quotesvalue" maxLines="1">bind{detail[openidx]}</textbox>
<textbox width="100%" class="quoteslabel" maxLines="1">Prev Close:</textbox>
<textbox width="100%" class="quotesvalue" maxLines="1">bind{detail[prevtradeidx]}</textbox>
<textbox width="100%" class="quoteslabel" maxLines="1">Cap:</textbox>
<textbox width="100%" class="quotesvalue" maxLines="1">bind{detail[capidx]}</textbox>
<textbox width="100%" class="quoteslabel" maxLines="1">P/E:</textbox>
<textbox width="100%" class="quotesvalue" maxLines="1">bind{detail[ratioidx]}</textbox>
</gridbox>
</prototype>
<prototype name="newsitem" extends="Box" layout="vertical" focusable="true" width="100%">
<attribute name="title">
this.children[0].value = this.title;
</attribute>
<attribute name="link"/>
<attribute name="description"/>
<attribute name="pubdate"/>
<textbox class="newstitle" width="100%"/>
</prototype>
<prototype name="chart" class="chart" extends="ImageBox" layout="vertical" width="100%" halign="center" valign="center" focusable="false" transform="stretch">
<attribute name="symbol">
this.url = chartURL + this.symbol;
</attribute>
</prototype>
<prototype name="inputitem" width="100%" layout="vertical" focusable="false" extends="Box">
<attribute name="label">
this.children[0].value = this.label;
</attribute>
<attribute name="value">
this.children[1].value = this.value;
</attribute>
<textbox class="label"/>
<textbox class="textentry" height="100%" width="100%" focusable="true" maxLines="1"/>
<method name="onClick">
this.getInput();
</method>
<script><![CDATA[
// Save the current list coming in
quoteList = Cache.symbols;
// Get input from user
this.getInput = function()
{
// Use native textinput
var textInput = new NativeTextInput();
textInput.source = this;
textInput.title = this.label;
textInput.value = this.value;
textInput.length = 50;
// When done entering data
textInput.onDone = function()
{
// If no data entered...
if (this.value.length == 0)
{
msg = "You must enter at least one stock symbol. The list will be reset.";
show(errorScreen, 1);
return;
}
// Force upper case, set current list of quotes and show prefs screen
this.source.value = this.value.toUpperCase();
// Save the result into a global variable
quoteList = this.source.value;
// Return to the preferences screen
show(prefsScreen);
};
// When user cancelled entering data
textInput.onCancel = function()
{
// Return to the preferences screen
show(prefsScreen);
};
// Show the textinput box
show(textInput);
};
// User selected 'Reset' from the preferences screen
this.setValue = function(value)
{
this.value = value;
quoteList = Cache.symbols;
};
]]></script>
</prototype>
<prototype name="softkeys" extends="Box" layout="horizontal" width="100%">
<attribute name="left">
this.children[0].value = this.left;
this.children[0].visible = true;
</attribute>
<attribute name="right">
this.children[1].value = this.right;
this.children[1].visible = true;
</attribute>
<textbox width="100%" halign="left" visible="false"/>
<textbox width="100%" halign="right" visible="false"/>
</prototype>
<httprequest id="downloadQuotes" url="bind{quotesURL + escape(Cache.symbols)}" mimeType="text/plain" async="true">
<method name="onLoaded">
quotes = setQuotes(this.responseText);
displayScreen(); // Display main screen
</method>
<method name="onLoaded">
var response = this.responseText;
quotes = setQuotes(response);
if (quotes.length == 0) // No stock quotes returned
{
msg = "Unable to download the list of stock quotes.\r\n\r\nClick Ok to retry.";
show(dataError, 1);
}
else
displayScreen(); // Display main screen
</method>
</httprequest>
<httprequest id="downloadDetails" url="bind{quotesURL + currentSymbol}" mimeType= "text/plain" async="true">
<method name="onLoaded">
var allQuotes = setQuotes(this.responseText);
if (allQuotes.length == 0) // No details returned
{
msg = "Unable to download the detail information for the stock symbol: \r\n\r\n" + currentSymbol + "\r\n\r\n Click Ok to retry.";
show(dataError, 1);
}
else
{
detail = allQuotes[0];
displayScreen(); // Display details screen
}
</method>
</httprequest>
<httprequest id="downloadNews" url="bind{newsURL + currentSymbol}" filter="stockFilter.xsl" async="true">
<method name="onLoaded">
news = this.responseXML; // Save results
if (currentScreen == newsScreen) // If refresh was requested from the news screen, display it
displayScreen();
</method>
</httprequest>
<screen id="mainScreen" layout="vertical" autoReset="false"
onLeftSoftkey="exit()"
onRightSoftkey="getQuotes(true)"
onRightKey="currentScreen = detailsScreen; getDetails(this.focus.symbol, false);">
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<tabrow id="home_tab" active="0"/>
<scrollbox id="mainScroll" width="100%" height="100%" focusable="false" scrollbar="true" >
<script>
var ndx = 0;
</script>
<foreach var="q" items="quotes" if="quotes">
-->
<quote symbol="once{q[symbolidx]}" lasttrade="once{q[lasttradeidx]}" change="once{q[changeidx]}" position="once{ndx++}"/>
</foreach>
</scrollbox>
<softkeys left="Exit" right="Refresh"/>
</screen>
<screen id="detailsScreen" layout="vertical" autoReset="false"
onRightSoftkey="getDetails(currentSymbol, true)"
onLeftKey="currentScreen = mainScreen; displayScreen()"
onRightKey="currentScreen = newsScreen; displayScreen()">
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<tabrow id="quotes_tab" active="1"/>
<scrollbox width="100%" height="100%" focusable="true" scrollbar="true" >
<companyname value="bind{ detail[companynameidx] + '(' + detail[symbolidx] + ')'; }"/>
<stockdetail/>
<chart symbol="bind{currentSymbol}" height="100%"/>
</scrollbox>
<softkeys left="" right="Refresh"/>
</screen>
<screen id="newsScreen" layout="vertical" autoReset="false"
onRightSoftkey="refreshNews()"
onLeftKey="currentScreen = detailsScreen; displayScreen()"
onRightKey="currentScreen = prefsScreen; displayScreen()">
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<tabrow id="news_tab" active="2"/>
<scrollbox width="100%" height="100%" focusable="false" scrollbar="true" >
<companyname value="bind{ detail[companynameidx] + '(' + detail[symbolidx] + ')'; }"/>
<foreach var="i" items="news.item" if="news">
<newsitem title="once{i.title}"/>
</foreach>
</scrollbox>
<softkeys left="" right="Refresh"/>
</screen>
<screen id="prefsScreen" layout="vertical" autoReset="false"
onLeftKey="currentScreen = newsScreen; displayScreen()">
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<tabrow id="prefs_tab" active="3"/>
<box layout="horizontal" height="100%" width="100%">
<inputitem id="symbols" label="Enter quotes for home page:" value="bind{Cache.symbols}"/>
</box>
<method name="onLeftSoftkey">
// Reset the textbox contents to current cache value
this.children[2].children[0].setValue(Cache.symbols);
// With list reset, show the screen again (refresh)
displayScreen();
</method>
<method name="onRightSoftkey">
// Update the cached list
Cache.symbols = quoteList;
// Set the current screen to 'main' and get new quotes
currentScreen = mainScreen;
resetScreen = true;
getQuotes(true);
</method>
<softkeys left="Reset" right="Save"/>
</screen>
<screen id="loadingScreen" layout="vertical" halign="center" valign="center">
<textbox class="loadingtext" value="bind{loadingMsg}"/>
<imagebox id="loading" focusable="false" url="images/loading_animation.gif">
<method name="onShow">
this.animate(true); // Start animation
</method>
<method name="onHide">
this.animate(false); // Stop animation
</method>
</imagebox>
</screen>
<screen id="splashScreen" layout="vertical" halign="center" valign="center">
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<box height="100%" width="100%" layout="vertical" halign="center" valign="center">
<textbox class="splashtext" width="100%" halign="center" valign="center">
Loading, please wait ...
</textbox>
<imagebox id="splashloading" focusable="false" url="images/loading_animation.gif">
<method name="onShow">
currentScreen = mainScreen; // Start with the 'main' screen
this.animate(true); // Start animation
getQuotes(false); // Get app data
</method>
<method name="onHide">
this.animate(false); // Stop animation
</method>
</imagebox>
</box>
</screen>
<screen id="dataError" layout="vertical" valign="center" halign="center" onLeftSoftkey="exit()">
<method name="onRightSoftkey">
hide(this);
retryDataRequest();
</method>
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<box class="errorbox" valign="center" halign="center" layout="vertical">
<textbox valign="center" halign="center" width="100%" >
bind{msg}
</textbox>
</box>
<softkeys left="Exit" right="Ok"/>
</screen>
<screen id="errorScreen" layout="vertical" focusable="false" onLeftSoftkey="displayScreen();">
<imagebox url="images/yahoo_finance.png" width="100%" halign="center"/>
<textbox width="100%" height="100%" halign="center" valign="center">bind{msg}</textbox>
<softkeys left="Back"/>
</screen>
</moblet>