Tuesday, 29 July 2008

AJAX: How to user Yahoo! Stock Quote CVS service

If you are trying to use AJAX skills to build your stock quote tool and are looking for some stock price feeds, then this article could help you a lot. :) The sample Yahoo! Stock Quote HTTP string looks like this: If you type in the HTTP address above to your browser address bar, it will return you a string like

20.745,-0.385,2590659
If you want the full information about the symbol, you can use **f=sl1d1t1c1ohgvj1pp2wern** instead. Don’t sweat, here comes the explanation for each letter (or letter-digit pair)

* s: the symbol name
* l: last value (or current price). If you use l alone, you will get back a string similar to Mar 22 - 31.26
* l1: (letter l and the number 1) to just get the last value of the symbol
* d: d alone will give you 0, while d1 will return the current date (e.g. 3/22/2007)
* t: t by itself will request the yahoo-generated chart. However, you will get back the chart image with a whole bunch of other HTML garbage, e.g. src=http://chart.yahoo.com/c//y/yhoo.gif" alt="Chart">
* t1: the time of last update, for example 4:00pm.
* c: the change amount. Can either be used as c or c1.
* o: opening value
* h: high value
* g: low value
* v: volume
* j: 52-week low.
* j1: the market cap. This is string like "42.405B" for $42 billion. Man… that can buy **a lot** of hamburger
* p: after hour price (?)
* p1: (?)
* p2: change percentage e.g. "-0.10%"
* w: 52-week range
* e: EPS (Earning per share)
* r: P/E (Prince/Earning) ratio
* n: Company name

Wednesday, 23 July 2008

How to build a popular 3 column HTML laytou

There is a very famous and very popular 2 or 3 columns html framework layout which used by IBM, Sony etc etc, and which is very easy to build and maintain. Below is the screen shot of the layout. The key skills are used in this structure are CSS float style and clear styles. The float style sets or retrieves on which side of the object the text will flow. The clear style sets or retrieves whether the object allows floating objects on its left side, right side, or both, so that the next text displays past the floating objects.

From the screen shot you can see to build the 3 columns we usually set the first two div columns' float style to left and the last one to right. By the way the 3 div areas will be listed horizontally and properly. Then we have to set the followed/next div (in the screen shot, DIV D) clear style to left or both.

The reason to use clear style
As you all know, the div element is a block element. But by set the float to left or right will change the div element to a inline object. In this case the DIV A, DIV B and DIV C are actually inline objects and DIV D is a block object. If don't set the DIV D's clear style to left or both the DIV D will be located at very top/left area inside the DIV MAIN and will be overlapped with DIV A, B and C.

If you don't like the clear style at all, there is a alternative way to set up this html layout, which is put the DIV A, B and C in a table element and you can get the same effect because the table will always auto reset its size to suit for all the element inside it and it is a block element too.

layout

Tuesday, 8 July 2008

Stupid syntax difference between IE and Firefox

When you are doing javascript/AJAX development you probably will add a very useful function trim() into build-in String object to return a copy of a string without both leading and trailing spaces. To do so you just need simply add one sentence in front of your js file. Below is the coding I used in my js framework.

function String.prototype.trim() {return this.replace(/(^\s*)|(\s*$)/g,"");};

Unfortunately this sentence only works on IE browser. It caused an error on Firefox which cost me one hour this afternoon to figure it out. after I changed the sentence to the syntax shown below a peaceful world came back again.

String.prototype.trim = function() {return this.replace(/(^\s*)|(\s*$)/g,"");};

It is painful to find out these tiny differences and it always lets me down. :(  But from the positive side, it makes you always use the standard syntax rule to build your project.

Wednesday, 2 July 2008

My AJAX framework v1.0

Nothing special. Create a new object wjAjax inside there is a XMLHttpRequest object named xmlhttp. And then you can call the function getData (method, url, params, async, func) which attached in wjAjax class. If you call the getData function by asynchronized way, the function will return true or false. But if you call the getData function by synchronized way it will directly return the XMLHttpRequest object for further using.

function wjAjax ()
{
  try
  {
    if (window.XMLHttpRequest)
    {
      this.xmlhttp = new window.XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
      this.xmlhttp = new window.ActiveXObject("MSXML2.XMLHTTP.3.0");
      if (!this.xmlhttp)
        this.xmlhttp = new new window.ActiveXObject("MICROSOFT.XMLHTTP");
    }
  }
  catch (e) {return null;}
  this.isRunning = false;
  return this;
}

wjAjax.prototype.getData = getData;

function getData(method, url, params, async, func)
{
  if (this.isRunning) {return false;}
  if (!url) {return false;}
  if (async && !func) {return false;}
  var me = this; //alias of wjAjax object, for reference using in onreadystatechange method.
  method = method || "get";
  params = params || "";
  try
  {
    if (method.toLowerCase() == "get")
    {
      this.xmlhttp.open("get", url+"?"+params, async);
      params = null;
    }
    else if (method.toLowerCase() == "post")
    {
      this.xmlhttp.open("post", url, async);
      this.xmlhttp.setRequestHeader("Method", "POST "+url+" HTTP/1.1");
      this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    }
    if (async)
    {
      this.xmlhttp.onreadystatechange = function()
      {
        if (this.readyState == 4)
        {
          me.isRunning = false;
          if (this.status == 200) {func(this);}
          else {alert ("HTTP server error. The HTTP server response status code is " + this.status);}
        }
      }
    }
    this.isRunning = true;
    this.xmlhttp.send(params);
    if (!async)
      this.isRunning = false;
  }
  catch (e) {alert("Run time error: "+e.message); return false;}
  if (async)
    return true;
  else
    return this.xmlhttp;
}

Monday, 30 June 2008

Dynamically insert new function to current html page - NEW SCENARIO

I have introduced two different way to insert new function in current html page dynamically. But there is a very tricky situation here which I think I should explain more. Let us say there are three html pages: main.htm, p1.htm and p2.htm. main.htm is actually the container of p1.htm and p2.htm and there is a nav control switch can help user jump between p1.htm and p2.htm pages. Now I want to add a new js function into the onunload event of main.htm page, which make sure a particular function will be invoke when user close the main.htm page no matter he/she is viewing p1.htm or p2.htm. To do so add the js code below to p1.htm (we suggest the p1.htm will be the first page shown in main.htm).
window.top.eval("window.onunload=function(){alert('new func...')};");
If you use window.eval instead of window.top.eval to create the new function, then when you jump to p2.htm and close the window the main.htm can't find the proper onunload function to call. I reckon the reason is the function point is only relying on the window object which you called the eval function from.

Wednesday, 2 April 2008

Javascript: How to preload audio by Windows Media Player with code sample

In my last article I explained how to preload images by HTML IMG element and javascript. Now I am going to show you the way to preload the audio.

This skill is used for one of our client. In the SCORM course we created for this client there are lots of background audio clips. Our client want the audio could be playing automatically without any delay when user go into the particular page, which means we have to preload all the audio clips at the very beginning for further using. In this case, I am using Windows Media Player to preload all the audios.

To do so, obviously we have to create a WMP object, hide it, set its autostart parameter to ture and set its mute to true. And then in the HTML page onload event, we transfer all the audio clip files one by one to the media player, and monitor the downloaded percentage and current status values of media player to refresh the progress bar. If the media player downloaded 100% I will send another audio to it.

There are two things I have to say. One is the media player downloading and buffering only happened after the HTML page onload event, because before that there is no WMP object at all. This thing is different with image preload rule because the IMG element is a internal HTML object but WMP is not. Another thing is there are two confusing events in WMP, buffering and downloading. In sample way, buffering could be fired more than once but downloading only be fired once and it will stop when WMP downloaded 100% of current file. So downloading is exactly the event we should take care of.

The link followed is a full function sample to preload images and a audio clip (singing in the rain) to your local machine by javascript and WMP, which is my personal album. Please click my album to try it. It is fully tested on IE7 and Firefox2.

The coding below is the key function to monitor media player running status.

var _currPrecent = 0;
function mediaDetector()
{ 
  var oWMP = document.getElementById("WMP"); 
  if (oWMP.playState == 10) {// state Ready means current URL is unavailable 
    window.clearInterval(_tId); 
    _tId = 0; 
    if (_currMedia >= _totalMedia) { 
      document.getElementById("icontext").innerHTML = _sProgress+"Media Loading... 100%"; 
      window.setTimeout("reLocateHTML()",1000); 
      return; 
    } 
    else { 
      reloadMedia(); 
    } 
  } 
  if (_mediaBuffering && oWMP.network.downloadProgress == 100) { 
    window.clearInterval(_tId); 
    _tId = 0; 
    _mediaBuffering = 0; 
    if (_currMedia >= _totalMedia) { 
      document.getElementById("icontext").innerHTML = _sProgress+"Media Loading... 100%"; 
      window.setTimeout("reLocateHTML()",1000); 
      return; 
    } 
    else { 
      reloadMedia(); 
    } 
  } 
  if (_currPrecent <= oWMP.network.downloadProgress || _currPrecent == 100) { 
    _currPrecent = oWMP.network.downloadProgress; 
    document.getElementById("icontext").innerHTML = _sProgress+"Media Loading... " 
      +Math.round(((_currMedia-1)/_totalMedia)*100)+"%<br/>" 
      +"--Media file "+_currMedia
      +"(total "+_totalMedia+")... "+oWMP.network.downloadProgress+"%";    
  }
}

Thursday, 6 March 2008

Javascript: How to preload images

The first thing you should know is, the body onload event will fire immediately after the browser loads all the html object, or we say html element. This is the key point we use to create the image preload widget.

So first of all, we declare a image array which included all the paths of the images we want to preload. And then we user javascript to create image elements (<img />) for every single image path in the array, and in the image onload event, we insert a function to refresh loading counter. Finally, we insert auto jump function to body onload event to jump to the actually page we want, in this case, it is google.com.

* Please remember the image path has to be an available path, or the image onload event will not fire and the counter will not show the correct percentage. 

The simple code below create a loader page, which will preload 4 images first and then auto jump to google.com. The code was tested on IE7 and FIrefox2.

<html>
<head>
<script type="text/javascript">

var _currImg = 0;
var _totalImg = 0;
var _sURL = "htt"+"p://www.google.com";

var _arrImg = new Array(
  "img_1.jpg",
  "img_2.jpg",
  "img_3.jpg",
  "img_4.jpg"
)

function createHTMLEl()
{
  _totalImg = _arrImg.length;

  h = "<div id='icon' style='position:absolute;left:0px;top:0px;"
    +"width:220px;height:120px;'>"
    +"<div style='width:100%;height:90px;'>"
    +"<span id='icontext' style='font-family:tahoma,arial;font-size:8pt;"
    +"font-weight:bold;'>Graphic Loading... 0%</span>"
    +"<span>&nbsp;&nbsp;&nbsp;</span>"
    +"<img src='load.gif' align='absmiddle'/>"
    +"</div>"
    +"<div style='text-align:center;'>"
    +"<input type='button' value='Skip' onclick='NextPage();'/>"
    +"</div>"
    +"</div>";

  for (var i = 0; i < _arrImg.length; i++)
  {
    h += "<img src='"+_arrImg[i]+"'"
      +"style='visibility:hidden;width:0px;height:0px;'"
      +"onload='refreshProgressBar();'/>";
  }
  document.body.innerHTML += h;
}

function refreshProgressBar()
{
  _currImg += 1;
  if (_currImg < _totalImg) {
    document.getElementById("icontext").innerHTML = "Graphic Loading... "
      +Math.round((_currImg/_totalImg)*100)+"%";
  }
  else {
    document.getElementById("icontext").innerHTML = "Graphic Loading... 99.9%";
  }
}

function resetIconPos()
{
  var o = document.getElementById("icon");
  o.style.left = Math.round((document.body.clientWidth - o.offsetWidth)/2)+"px";
  o.style.top = Math.round((document.body.clientHeight - o.offsetHeight)/2)+"px";
}

function reLocateHTML()
{
  document.getElementById("icontext").innerHTML = "Graphic Loading... 100%";
  window.location.href = _sURL;
}
</script>
</head>
<body onload="reLocateHTML();">
<script type="text/javascript">
createHTMLEl();
resetIconPos();
</script>
</body>
</html>

Saturday, 1 March 2008

Enjoy: Independence Day

Good morning. !@#$% - Good morning.
In less than an hour, aircraft from here will join others from around the world. And you will be launching the largest aerial battle in the history of mankind. Mankind - that ~ word should have new meaning for all of us today. We can't be consumed by our petty differences anymore. We will be united in our common interests. Perhaps its fate that today is the 4th of July, and you will once again be fighting for our freedom, not from tyranny, oppression, or persecution - but from annihilation. We're fighting for our right to live, to exist. And should we win the day, the 4th of July will no longer be known as an American holiday, but as the day when the world declared in one voice: "We will not go quietly into the night! We will not vanish without a fight! We're going to live on! We're going to survive!" Today, we celebrate our Independence Day!

Thursday, 28 February 2008

Enjoy: 2008 Beijing Olympic Games (8th~24th, Aug, 2008)

2008 Beijing Olympic Games start at 8th Aug 2008, there are total 35 sports in the Olympic Games. By the flash shows below, you can see all of these 35 sports icons. If you click any one of these icons, it will link you to the related sport page in 2008 Beijing Olympic Games official website. Enjoy it. :)

Wednesday, 27 February 2008

Javascript: 2 ways to insert new function dynamically

The coding below help you to create and insert new javascript function into a loaded html page. Which is very useful for dynamic external js libs binding. I personally recommend the first way:
function addFunc()
{
var sFunc = ""
+"function myOnUnLoad()"
+"{"
+"alert('unload...');"
+"};"
+"window.document.body.onunload = myOnUnLoad;";

window.eval(sFunc);
}
Second way, by this way you have to write down all your code in a external js file, in this case, let us say myjs.js file:
function addFunc()
{
var o = window.document.createElement("script");
o.type="text/javascript";
o.src="myjs.js";

//if you use o.innerHTML="..." or o.innerText="..." here, you will get a
//runtime error. That is why you have to use a external js file, and use
//o.scr="myjs.js" to insert function code


window.document.getElementsByTagName("head")[0].appendChild(o);
}

//-- code in myjs.js file
window.document.body.onunload = function ()
{
alert("unload...");
}

Javascript: tricky window.open() on IE6

If you write javascript regularly, you must be very familiar with function window.open(), which open an external browser window with particular features (size, position, scroll bars, status bar etc.) This function is supported by almost all the popular browsers (IE6/7, Firefox, Opera and Safari), but I found in one particular case it doesn't work properly on IE6, which is when you try to show a menu bar on the browser window. Followed is the code.
//page1.htm source code <html>
<head>
<title></title>
<script type="text/javascript">
function popup()
{
var style = "width=300,height=300,left=0,top=0,"
+"toolbar=yes,scrollbars=no,resizable=no,menubar=yes,status=yes,location=yes";
var o = window.open("page2.htm","page2",style);
}
</script>
</head>
<body>
click <a href="javascript:void(0);" onclick="popup();">here</a>.
</body>
</html>
////page2.htm source code
<html>
<head>
<title>page two</title>
</head>
<body>
<div style="position:absolute;left:0px;top:0px;
width:300px;height:300px;background-color:yellow;"></div>
</body>
</html>
When I launch page1.htm by all the other browser except IE6, and click the link in the page, it will open page2.htm in a pop-up window with correct clientHeight and clientWidth value, in this case they are 300 and 300. But when I do the same thing by IE6, I got a pop-up window with 19px more height space in the window. And if I switch off the menubar from the javascript code, it works ok. Below is the screenshot of this bug?

Javascript: basic XML object searching

In this case, let's suggest we have already declared a xml node object oXml, the most popular search xPaths are:
//search by attribute
oXml.selectNodes("//tag1/tag2[@id='1' and type='1']");
//search by tag text value
oXml.selectNodes("//tag1/tag2[text='text']");

Javascript: the first dodgy, execute javascript function in browser address bar

In Browser addess bar, type in javascript: and then followed by the javascript function you wanna execute, press enter key. Below is a example.
javascript:alert(document.getElementById("id").outerHTML);