<!--NoAd-->
#backgroundDIV {
position: absolute;
width: 280;
height: 290;
background-color: black;
cursor: arrow;
}
#chartAppletDIV {
position: absolute;
left: 4;
top: 24;
width: 270;
height: 140;
background-color: black;
z-index: 1;
}
#indexesDIV {
position: absolute;
left: 4;
top: 172;
width: 270;
height: 10;
padding: 2;
background-color: #FF7200;
font-size: 7pt;
font-family: Verdana;
font-weight: bold;
text-align: center;
cursor: hand;
z-index:2;
}
#adDIV {
position: absolute;
left: 20;
top: 224;
height: 62;
width: 236;
background-color: black;
}
.customize {
font-size: 7pt;
font-family: Verdana;
font-weight: bold;
background-color: black;
color: #FF7200;
border: 1 solid #FF7200;
}
.menu {
position: absolute;
height: 10;
padding-left: 2;
padding-right: 2;
border: 1 solid #FF7200;
color: #FF7200;
font-size: 7pt;
font-family: Verdana;
text-align: left;
cursor: hand;
z-index:3;
}
#customizeDIV {
position: absolute;
left: 4;
top: 169;
width: 270;
height: 15;
color: #FF7200;
background-color: black;
font-size: 7pt;
font-family: Verdana;
font-weight: bold;
text-align: center;
z-index: 2;
visibility: hidden;
}
Figure 3 Fortune Personal Stock Chart HTML
<!-- Title: Fortune Personal Stock Chart -->
<!-- Type: ActiveDesktop component -->
<!-- Author: Josh Hochman (jhochman@pathfinder.com) -->
<!-- based on original code by Stefan Winz -->
<!-- Date: 9-31-97 -->
<HTML>
<HEAD>
<!-- Always expire this page because the content will always be fresh -->
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<TITLE>Fortune Desktop Component</TITLE>
<!-- to save space here, link in a stylesheet -->
<LINK REL=STYLESHEET TYPE="text/css" HREF="styles.html" TITLE="Styles">
<!-- chart.js contains all JavaScript that drives this page -->
<SCRIPT LANGUAGE="JavaScript" SRC="chart.js"></SCRIPT>
<!-- a few wrapper functions to take care of the ADO stuff -->
<!-- ADO is "ActiveX Data Object" - just a fancy name for -->
<!-- OLE DB routines. They manipulate a cursor in the TDC's recordset-->
<SCRIPT LANGUAGE="VBScript">
sub moveFirst (theTDC)
theTDC.Recordset.MoveFirst
end sub
function getValue (theTDC,theName)
getValue = theTDC.Recordset(theName)
end function
function getRecordCount (theTDC)
getRecordCount = theTDC.Recordset.RecordCount
end function
function moveNext (theTDC)
theTDC.Recordset.MoveNext
end function
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#000000" LEFTMARGIN=0 TOPMARGIN=0 onload=init()>
<!-- TDC is a "Tabular Data Control", just an ADO with a few web-related-->
<!-- functions added on. The important thing here is "DataURL" which is -->
<!-- where the data is coming from -->
<OBJECT ID=TDC CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
<PARAM NAME="TextQualifier" VALUE=""">
<PARAM NAME="FieldDelim" VALUE="|">
<PARAM NAME="UseHeader" VALUE="False">
<PARAM NAME="DataURL" VALUE="">
<PARAM NAME="SortColumn" VALUE="Column1">
</OBJECT>
<!-- we have to stick this here because of the way that browsers load -->
<!-- code. Now that TDC has been declared, we tie a function to it's -->
<!-- notify routine. *BUG*: you have to attatch the TDC to another -->
<!-- object, or the notify event will never fire. That is why there is -->
<!-- a hidden DIV that displays TDC -->
<SCRIPT LANGUAGE="JavaScript1.2">
TDC.ondatasetcomplete = TDCcomplete;
</SCRIPT>
<DIV id=backgroundDIV>
<DIV STYLE="width: 280;font-family: Verdana;font-size:13;font-weight: bold;color:
#FF7200;text-align:center;padding:4">
PERSONAL FORTUNE STOCK CHART
</DIV>
<!-- chartAppletDIV is the Java applet that does all the drawing-->
<DIV id=chartAppletDIV>
<applet code=draw.class
id=chart
width=270
height=140>
<param name=colorBGR value=0>
<param name=colorBGG value=0>
<param name=colorBGB value=0>
</applet>
</DIV>
<!-- indexesDIV displays all the stock symbols, and lets you -->
<!-- switch between them. handleMousedown takes care of the that-->
<DIV id=indexesDIV>
<SPAN id=DJIASPAN
onmouseover="style.color='white'"
onmouseout="if (0 != theChoice) style.color='black'"
onmousedown="if (0 != theChoice) handleMouseDown(this)">DJIA</SPAN>
<SPAN id=SP500SPAN
onmouseover="style.color='white'"
onmouseout="if (1 != theChoice) style.color='black'"
onmousedown="if (1 != theChoice) handleMouseDown(this)">S&P500</SPAN>
<SPAN id=NASDAQSPAN
onmouseover="style.color='white'"
onmouseout="if (2 != theChoice) style.color='black'"
onmousedown="if (2 != theChoice) handleMouseDown(this)">NASDAQ</SPAN>
<SPAN id=NYSESPAN
onmouseover="style.color='white'"
onmouseout="if (3 != theChoice) style.color='black'"
onmousedown="if (3 != theChoice) handleMouseDown(this)">NYSE</SPAN>
<SPAN id=AMEXSPAN
onmouseover="style.color='white'"
onmouseout="if (4 != theChoice) style.color='black'"
onmousedown="if (4 != theChoice) handleMouseDown(this)">AMEX</SPAN> -
<SPAN id=custom1SPAN
onmouseover="style.color='white'"
onmouseout="if (5 != theChoice) style.color='black'"
onmousedown="if (5 != theChoice) handleMouseDown(this)"></SPAN>
<SPAN id=custom2SPAN
onmouseover="style.color='white'"
onmouseout="if (6 != theChoice) style.color='black'"
onmousedown="if (6 != theChoice) handleMouseDown(this)"></SPAN>
</DIV>
<!-- statsDIV will get filled in with the current value of the stock -->
<DIV id=statsDIV class=menu style="left: 4;top: 192;width: 138;">
current value: <SPAN id=currentPrice>0</SPAN></SPAN>
</DIV>
<!-- refreshMenuDIV is either the refresh button, wich calls refresh, -->
<!-- or it is the cancel button when customizing. If we are customizing -->
<!-- then clicking this button (which says "cancel") will simulate -->
<!-- the user pressing the ESC key and call keydown, effectively -->
<!-- cancelling the customization -->
<DIV id=refreshMenuDIV class=menu style="left: 144;top: 192;width: 55;"
onmouseover="style.color='white'"
onmouseout="style.color='#FF7200'"
onmousedown="style.color='#FF7200';if (theState == 'customize')
{event.keyCode =27;keydown()} else {refresh()}">
REFRESH
</DIV>
<!-- customizeMenuDIV is either the customize button, which calls the -->
<!-- customize function, or it is the save button, which will simulate -->
<!-- the user pressing "return" and will call keydown, effectively -->
<!-- saving the customization -->
<DIV id=customizeMenuDIV class=menu style="left: 201;top: 192;width: 60;"
onmouseover="style.color='white'"
onmouseout="style.color='#FF7200'"
onmousedown="style.color='#FF7200';if (theState == 'customize')
{event.keyCode = 13;keydown()} else {customize()}">
CUSTOMIZE
</DIV>
<DIV id=link class=menu style="border:0 none;:top:210;text
align:center;width:270"
onmouseover="style.color='white'"
onmouseout="style.color='#FF7200'"
onmousedown="window.open('http://www.fortune.com')">
Go to the Fortune website...
</DIV>
<!-- customizeDIV is a hidden DIV that gets shown when the user clicks -->
<!-- the customize button. It is a form that lets you change the last -->
<!-- two symbols -->
<DIV id=customizeDIV>
<FORM id=theForm>
DJIA S&P500 NASDAQ NYSE AMEX -
<INPUT id=custom1 class=customize SIZE=4>
<INPUT id=custom2 class=customize SIZE=4>
</FORM>
</DIV>
<DIV id=adDIV><!--#exec cgi="/pfinclude@pfadspace"--></DIV>
<!-- this hidden layer holds the cursor's value in the first column of -->
<!-- the current record in the TDC's recordset. If this isn't here, then-->
<!-- ondatasetcomplete events never get fired. Oh well. I guess it -->
<!-- doesn't hurt that much. -->
<DIV id=poop DATASRC=#TDC DATAFLD="Column1"
style="layout:fill;position:absolute;
top:0;visibility:hidden">
</DIV>
</DIV>
</BODY>
</HTML>
Figure 5 JavaScript for Databinding
<!-- NoAd -->
var symbols = new Array(7); // the seven symbol objects
var theState = 'init'; // internal state
var theChoice = 0; // the currently chosen symbol
var startTime = (9*60) + 30; // 9:30 a.m., in minutes since midnight
var endTime = (16*60) + 30; // 4:30 p.m., in minutes since midnight
var leftOffset = 60; // offsets for the chart section
var topOffset = 20;
var bottomOffset = 20;
var rightOffset = 20;
var top = 0; // values to help with offset calculations
var left = 0;
var bottom = 140;
var right = 270;
var loadDataTimeout = 0; // timeout for loading data
var drawChartTimeout = 0; // timeout for drawing the chart
var blink = 0; // for blinking "loading"
var blinker; // blinker intervalID
document.onkeydown = keydown; // capture keydown events with my own function
// Init - this function loads in the two personal stocks (if there is a cookie
// that contains them) and creates five symbol objects. Next it calls three
// asynchronous functions to load the data, convert the data, and draw the chart
function init(){
// either get the cookie, or bake some ourselves
var cookie1 = getCookie("custom1");
var cookie2 = getCookie("custom2");
if (!cookie1) cookie1 = "TWI";
if (!cookie2) cookie2 = "MRV";
// preload the customize form with our values
theForm.custom1.value = cookie1;
theForm.custom2.value = cookie2;
// create a bunch of symbol objects
symbols[0] = new Symbol (TDC,DJIASPAN,"http://quote.pathfinder.com/money/quote/
qclie.cgi?dukebert=INDU");
symbols[1] = new Symbol (TDC,SP500SPAN,"http://quote.pathfinder.com/money/quote/
qclie.cgi?dukebert=INX");
symbols[2] = new Symbol (TDC,NASDAQSPAN,"http://quote.pathfinder.com/money/quote/
qclie.cgi?dukebert=COMPX");
symbols[3] = new Symbol (TDC,NYSESPAN,"http://quote.pathfinder.com/money/quote/
qclie.cgi?dukebert=NYA.X");
symbols[4] = new Symbol (TDC,AMEXSPAN,"http://quote.pathfinder.com/money/quote/
qclie.cgi?dukebert=XAX.X");
symbols[5] = new Symbol (TDC,custom1SPAN,"http://quote.pathfinder.com/money/
quote/qclie.cgi?dukebert=" + cookie1);
symbols[6] = new Symbol (TDC,custom2SPAN,"http://quote.pathfinder.com/money/
quote/qclie.cgi?dukebert=" + cookie2);
// fill in the customizable symbols on the interface
custom1SPAN.innerText = theForm.custom1.value + " ";
custom2SPAN.innerText = theForm.custom2.value;
loadTDC(symbols[0].TDC,symbols[0].dataURL); // load the first TDC
theChoice = 0;
symbols[theChoice].SPAN.style.color = "white"; // make it white
drawTable(); // draw the table (sans data)
loadData(theChoice); // load in the data (asynchronous)
drawChart(theChoice); // draw the chart (asynchronous)
}
// handleMouseDown - loops through all the symbol objects and sets the color
// of their label SPAN to black. when it matches the SPAN passed in to the
// SPAN of one of the symbols, it makes it white, erases the chart, loads the
// data (if needed), and redraws the chart.
//
// theObject - the SPAN that was clicked (should match one of the
// symbol.SPAN objects)
function handleMouseDown(theObject){
if (theState != "idle") return;
chart.DrawRect(left,top,right,bottom,0,0,0); // erase the chart
for (var j=0;j < symbols.length;j++){
// why is everything in a timeout? because stuff doesn't work
// correctly if it isn't. Oh well.
if (symbols[j].SPAN == theObject) { // matching symbol
theChoice = j;
symbols[j].SPAN.style.color = 'white';
if (!symbols[j].loaded) { // needs to get data
loadTDC(symbols[j].TDC,symbols[j].dataURL);
loadData(j);
} else { // just draw new y labels
setTimeout("drawYLabels(" + j + ")",5);
}
drawTable();
setTimeout("drawChart(" + j + ")",4);
} else { // if not the symbol,
// make sure it's black
symbols[j].SPAN.style.color = 'black';
}
}
}
// refresh - called when the refresh button is pressed. This function will set
// the "loaded" state of all the symbol objects to 0, effectively clearing
// them. It also reloads the current symbol.
function refresh(){
if (theState != "idle") return;
for (var j=0;j < symbols.length;j++){
symbols[j].loaded = 0;
}
// clear the chart and load and draw the current symbol
chart.DrawRect(left,top,right,bottom,0,0,0);
loadTDC(symbols[theChoice].TDC,symbols[theChoice].dataURL);
loadData(theChoice);
drawTable();
setTimeout("drawChart(" + theChoice + ")",4);
}
// getCookie - a simple function to return the value of a particular
// "chip" in the cookie for this page
//
// theName - the name part of the name-value pair
function getCookie(theName){
var theValue = document.cookie;
if (theValue.indexOf(theName) == -1) return 0;
theValue = theValue.substring(theValue.indexOf(theName));
theValue = theValue.substring(0,theValue.indexOf(";"));
return theValue.substring(theValue.indexOf("=")+1);
}
// loadTDC - sets the data source for a TDC and starts the process
// of getting the data.
//
// theTDC - the tabular data control object
// theURL - the URL containing the tabular data
function loadTDC(theTDC, theURL){
theState = "loading";
theTDC.DataURL = theURL;
theTDC.Reset();
blinker = setInterval("blinkme()",500);
}
// customize - called when the "customize" button is pressed. Reveals
// the DIV that contains the customize boxes, and changes some of the
// values in the buttons (REFRESH -> CANCEL) (CUSTOMIZE -> SAVE).
function customize(){
theState = "customize";
customizeMenuDIV.innerText = "SAVE";
refreshMenuDIV.innerText = "CANCEL";
customizeDIV.style.visibility = 'visible';
}
// keydown - traps keydown events. If in customize state, then do
// something depending upon what key is pressed - "return" will save
// any changes, while ESC will cancel.
function keydown(){
if (theState == 'customize' && event.keyCode == 13){ // return pressed
theForm.custom1.value = theForm.custom1.value.toUpperCase();
theForm.custom2.value = theForm.custom2.value.toUpperCase();
// set the cookie for this document with 2 values
var expiration = "Saturday, 01-Jan-2000 00:00:00 GMT"
document.cookie = "custom1=" + theForm.custom1.value + ";" + "expires=" +
expiration + ";" + "domain: pathfinder.com;" + "path: /";
document.cookie = "custom2=" + theForm.custom2.value + ";" + "expires=" +
expiration + ";" + "domain: pathfinder.com;" + "path: /";
// change everything back to the way it was (SAVE -> CUSTOMIZE) (CANCEL ->
//REFRESH)
customizeDIV.style.visibility = 'hidden';
customizeMenuDIV.innerText = "CUSTOMIZE";
refreshMenuDIV.innerText = "REFRESH";
refreshMenuDIV.style.visibility = 'visible';
custom1SPAN.innerText = theForm.custom1.value + " ";
custom2SPAN.innerText = theForm.custom2.value;
// actually create the symbol objects
symbols[5] = new Symbol (TDC,custom1SPAN,"http://quote.pathfinder.com/money/
quote/qclie.cgi?dukebert=" + theForm.custom1.value);
symbols[6] = new Symbol (TDC,custom2SPAN,"http://quote.pathfinder.com/money/
quote/qclie.cgi?dukebert=" + theForm.custom2.value);
if (!navigator.cookieEnabled) alert("Your changes will not be saved unless
you enable your browser to accept cookies.");
theState = "idle";
} else if (theState == 'customize' && event.keyCode == 27){ // ESC pressed
theForm.custom1.value = custom1SPAN.innerText; // reset the form values
theForm.custom2.value = custom2SPAN.innerText;
// change everything back to the way it was (SAVE -> CUSTOMIZE) (CANCEL ->
//REFRESH)
customizeDIV.style.visibility = 'hidden';
customizeMenuDIV.innerText = "CUSTOMIZE";
refreshMenuDIV.innerText = "REFRESH";
refreshMenuDIV.style.visibility = 'visible';
theState = "idle";
}
}
// drawTable - draws the chart that the stocks are charted on
function drawTable(){
var x = 0;
var theTime = 9;
var fixedTime = 0;
var labelOffset = 0;
chart.init(); // initialize the java applet
// draw the left and bottom lines.
// for some reason, sometimes the first draw call never executes,
// therefore, call it twice to make sure it does execute
chart.DrawLine(leftOffset,topOffset,leftOffset,bottom - bottomOffset,85,85,85);
chart.DrawLine(leftOffset,topOffset,leftOffset,bottom - bottomOffset,85,85,85);
chart.DrawLine(leftOffset,bottom - bottomOffset,right - rightOffset + 7,bottom -
bottomOffset,85,85,85);
var chunkSize = Math.round((right - leftOffset - rightOffset)/14);
for (i=1;i<8;i++){
x = leftOffset + chunkSize * i * 2;
// draw a light line for half-hour segments
chart.DrawLine(x,topOffset,x,bottom - bottomOffset - 1,40,40,40);
// draw a darker line for hour segments
chart.DrawLine(x - chunkSize,topOffset,x - chunkSize,bottom - bottomOffset -
1,85,85,85);
}
x = leftOffset + chunkSize;
for (i=9;i<16;i++){ // slap some labels on there, also, do some math to
// convert the time
if (i != 9) x += chunkSize * 2;
fixedTime = ++theTime;
labelOffset = 13;
if (theTime > 12) {
fixedTime = theTime - 12;
labelOffset = 7;
}
chart.DrawText(fixedTime + ":00",x - labelOffset,bottom - bottomOffset/2 +
5,255,102,0);
}
}
// loadData - an asynchronous function (uses setTimeout to keep calling itself
// until a certain global state is reached) that uses the ADO (Active Data Object)
// part of the TDC object to convert market data into an array of points to plot on
// the chart.
//
// theSymbol - the symbol object that contains the TDC and array of points
function loadData(theSymbol){
var x = 0;
var y = 0;
if (theSymbol > 7) return; // obviously something is wrong!
if (theState != "dataWaiting") { // haven't gotten all the data yet, so use
// settimeout
// to call this function again
loadDataTimeout = setTimeout("loadData("+theSymbol+")",500);
} else { // have data - convert it to points on chart
theState = "fixing";
clearTimeout(loadDataTimeout);
moveFirst(symbols[theSymbol].TDC); // use VBScript wrapper function
symbols[theSymbol].numRecords = getRecordCount(symbols[theSymbol].TDC);
if (symbols[theSymbol].numRecords == 1) { // no data, return
theState = "idle";
clearInterval(blinker);
chart.DrawText("",100,100,255,102,0); // nudge the java applet
chart.DrawRect(10,60,50,30,0,0,0); // erase the text
chart.DrawText("No Data",20,75,255,102,0);
return 0;
}
var j = 0;
for (i=0;i<symbols[theSymbol].numRecords - 1;i++){
var minutes = getValue(symbols[theSymbol].TDC,"Column1");
if ((minutes > 570) && (minutes < 990)){
// if last record, then save the last time
if (i == (symbols[theSymbol].numRecords - 1))
symbols[theSymbol].lastTime = x;
x = translateX(getValue(symbols[theSymbol].TDC,"Column1"));
// don't translate y values yet
y = getValue(symbols[theSymbol].TDC,"Column2");
symbols[theSymbol].data[j] = new Point(x,y) // add a point object
// do some comparisons to keep the min Y and max Y values
if (!j) symbols[theSymbol].maxY = y;
if (y > symbols[theSymbol].maxY) symbols[theSymbol].maxY = y;
if (!j) symbols[theSymbol].minY = symbols[theSymbol].maxY;
if (y < symbols[theSymbol].minY) symbols[theSymbol].minY = y;
j++;
}
moveNext(symbols[theSymbol].TDC);
}
// last name/value pair is stock ticker/current value, just get the value
symbols[theSymbol].currentPrice =
getValue(symbols[theSymbol].TDC,"Column2");
drawYLabels(theSymbol); // draw Y values with min and max Y
symbols[theSymbol].data[0].y =
translateY(symbols[theSymbol].data[0].y,theSymbol);
// translate all Y values
for (i=0;i < symbols[theSymbol].data.length;i++){
symbols[theSymbol].data[i].y =
translateY(symbols[theSymbol].data[i].y,theSymbol);
}
theState = "idle";
symbols[theSymbol].loaded = 1;
}
}
// drawChart - draws the activity of the symbol object. An asynchronous function
// that uses settimeout to keep calling itself until an idle state is achieved.
//
// theSymbol - the symbol object that contains the TDC and array of points
//
function drawChart(theSymbol){
if (theState != "idle"){ // not idle, so call settimeout on this function
// to call it again 1/2 second later
drawChartTimeout = setTimeout("drawChart("+theSymbol+")",500);
} else { // loop throught the points and draw 'em
theState = "drawing";
clearTimeout(drawChartTimeout);
var numEntries= getRecordCount(symbols[theSymbol].TDC);
for (i=3;i < symbols[theSymbol].data.length - 1;i++) {
chart.DrawLine(leftOffset + symbols[theSymbol].data[i-1].x,topOffset +
symbols[theSymbol].data[i-1].y,leftOffset + symbols[theSymbol].data[i-
2].x,topOffset + symbols[theSymbol].data[i-2].y,0,255,0);
}
theState = "idle";
currentPrice.innerText = pround(symbols[theSymbol].currentPrice,1);
}
}
// drawYlabels - draws the label for the minimum and maximum stock values,
// and 2 values in between.
//
// theSymbol - the symbol object that contains the max and min Y values
function drawYLabels(theSymbol){
var theValue = 0.0;
clearInterval(blinker);
chart.DrawText("",100,100,255,102,0); // nudge the java applet
chart.DrawRect(10,60,50,30,0,0,0); // erase the blinking text
chart.DrawText(symbols[theSymbol].minY,leftOffset - 45,bottom -
bottomOffset + 5,255,102,0);
var chunkSize = 0.0;
chunkSize = (symbols[theSymbol].maxY - symbols[theSymbol].minY)/4;
for (var i=1;i<4;i++){
theValue = chunkSize * i;
theValue = theValue + parseFloat(symbols[theSymbol].minY);
theValue = pround(theValue,2);
chart.DrawText("",100,100,255,102,0);
chart.DrawText(theValue,leftOffset - 45,bottom - bottomOffset - 25 * i +
5,255,102,0);
chart.DrawLine(leftOffset,bottom - bottomOffset - i * 25,right -
rightOffset + 5,bottom - bottomOffset - i * 25,40,40,40);
}
chart.DrawLine(leftOffset,topOffset,right - rightOffset + 5,topOffset,40,40,40);
chart.DrawText(symbols[theSymbol].maxY,leftOffset - 45,top + topOffset +
5,255,102,0);
}
// translateX - converts a minutes after midnight value into an X coordinate
function translateX(theValue){
var value = Math.round((theValue - startTime) * (( right - leftOffset -
rightOffset +20)/420));
return (value <= 0) ? (( right - leftOffset - rightOffset +20)/420) : value;
}
// translateY - converts a stock value into a Y coordinate
function translateY(theValue,theSymbol){
var theDiff = symbols[theSymbol].maxY - symbols[theSymbol].minY;
return parseInt((100 * (1.0 - (theValue - symbols[theSymbol].minY) / theDiff)));
}
// TDCcomplete - gets called when TDC is done loading data - setting the
// state to dataWaiting
// should hold off any asynchronous functions from firing
function TDCcomplete(){
theState = "dataWaiting";
}
// Symbol - This is the constructor for a symbol object.
//
// aTDC - a Tabular Data Control (TDC) object that will contain the
// data for this symbol
// aSPAN - the SPAN tag that contains the link that makes the symbol active
// aDataURL- the URL for the data that gets loaded into The TDC
function Symbol (aTDC,aSPAN,aDataURL){
this.loaded = 0;
this.TDC = aTDC;
this.SPAN = aSPAN;
this.dataURL = aDataURL;
this.data = new Array();
this.maxY = 0;
this.minY = 0;
this.numRecords = 0;
this.lastTime = 0;
this.currentPrice = 0;
return this;
}
// Point - a simple object that holds and X,Y coordinate
//
// aX - the X coordinate
// aY - the Y coordinate
function Point (aX,aY){
this.x = aX;
this.y = aY;
}
function blinkme(){
if (!blink) {
chart.DrawText("",100,100,255,102,0); // nudge the java applet
chart.DrawText("Loading",20,75,255,102,0);
blink = 1;
} else {
chart.DrawText("",100,100,255,102,0); // nudge the java applet
chart.DrawRect(10,60,50,30,0,0,0); // erase the text
blink = 0;
}
}
// pround - precision round function (written by Bob Hartlaub)
// returns the rounded number
//
// num - the number to round
// precision - how many decimal places to round to
function pround(num, precision){
num = parseFloat(num); // turn num into a number
rndprec = Math.pow(10,(precision));
num = ((Math.round(num * rndprec)) / rndprec); // round to precision amount
//Fix code to avert javascript 1.2 internal precision problem
p_dot = /\./; // determine length of return string before doing addition
numstr = num.toString();
numstr_parts = numstr.split(p_dot);
pnum_prec_length = numstr_parts[0].length + precision + 1;// pre-decimal +
precision + decimal point
// end of fix
var pr = Math.pow( 10,(0 - precision - 1) ); // create precision # + xtra tenth
var pn = num + pr;
var pnum = pn.toString(); // turn value to a string
var pnumtrunc = pnum.substring(0, pnum_prec_length); // truncate xtra tenth
return pnumtrunc;
}