Wednesday, December 9, 2009

A Graph in Table Without Image

Here is a simple script to add a graph to a table cell. Each table row consists of 2 cells. The first cell contains a numeric value. For each row, in the second cell, the script creates a span with a width equal to the value in the first cell:


var tbl = document.getElementById('tbl');
for(var i=0; i<tbl.rows.length; i++){
var val = tbl.rows[i].cells[0].innerHTML;
var span = document.createElement("span");
span.style.width = val/100*100;
span.className = "graph";
var cell =tbl.rows[i].cells[1];
cell.style.textAlign= 'left';
cell.appendChild(span);
}


It assumes you set a style for a "graph" class. Alternatively, you could set background color in the script. Also, the maximum span width of 100 is assumed.

A side note: to create a rounded span in Firefox, use the following style for the "graph" class:
-moz-border-radius: 10px;

Friday, May 22, 2009

A Progress Bar Example

<div id='pbar' style='width:400px'>
<span id='pbar_internal' style='width:0px;'></span>
<
/div>

Create an array
with numbers from 1 to 5. The array will provide data for our progress bar.

var arr = [1, 2, 3, 4,5];

The initial array count is set at
0:

var curIndex =0;

Create variables holding references to the div and span elements:
var div = document.getElementById('pbar');
var span = document.getElementById('pbar_internal');

Save the div width
in a variable:
var parWidth = parseInt(div.style.width);

Create a
function that will update the span width depending on the value of
the current array count:

function showBar ()
{
if(curIndex < arr.length){ var spanWidth = parseInt(parWidth/arr.length * curIndex);
span.style.width
= spanWidth ; }
else
clearInterval(id);
}

To launch
this function, we will use a JavaScript setInterval method.

var id = setInterval ( showBar, 1000 );

What we
do here is we tell the browser to run the showBar function every second.
When the current array counter reaches the end of the array,
we cancel the setInterval method by calling the clearInterval method.

We are almost done now. However, the code above will work only
in IE
unless we use a specific span style
for Firefox and Opera. Here it is:

span {
display:
-moz-inline-box; /* Gecko proprietary */
display:inline
-block; /* supported by Opera and ? */
width:
25%;height:1em; /* width and height required */
vertical
-align:top; /* Gecko needs this */
}
/* IE, Opera & Gecko slight diff */

I
'll try to post a live demo later on.

Wednesday, May 20, 2009

Enumerate Array or Object

This is how you could enumerate properties of a JavaScript array:

var arr = ['a', 'b', 'c'];

for (var prop in arr)
alert (prop + ":"+ arr[prop]);

Result:
0:a
1:b
2:c

Thursday, March 26, 2009

Expand/Collapse Rows Dynamically with DOM and JavaScript

Suppose, you have a table structured as follows:




The first line for a new month is always a total of the project amounts. This structure comes from an sql query, using the Oracle GROUP BY CUBE clause. Would not it be nice to be able to see only the rows with intermediate totals, expanding this or that month if necessary.



Here is a set of JavaScript functions that collapses and expands table rows:



var tbl;

function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
return el;
else
return getParent(el.parentNode, pTagName);
}


function toggleSection(lnk){

var td = lnk.parentNode;
var table = getParent(td,'TABLE');
var len = table.rows.length;
var tr = getParent(td, 'tr');
var rowIndex = tr.rowIndex;
var rowHead=table.rows[rowIndex].cells[1].innerHTML;

lnk.innerHTML =(lnk.innerHTML == "+")?"-":"+";
vStyle =(tbl.rows[rowIndex+1].style.display=='none')?'':'none';

for(var i = rowIndex+1; i < len;i++){
if (table.rows[i].cells[1].innerHTML==rowHead){
table.rows[i].style.display= vStyle;
table.rows[i].cells[1].style.visibility="hidden";
}
}
}

function collapseRows(){
tables =document.getElementsByTagName("table");
for(i =0; i < tables.length;i++){
if(tables[i].className.indexOf("expandable") != -1)
tbl =tables[i];
}

if(typeof tbl=='undefined'){
alert("Could not find a table of expandable class");
return;
}

//assume the first row is headings and the first column is empty
var len = tbl.rows.length;
var link = '<a href="#" onclick="toggleSection(this);return false;">+ </a> ';

var rowHead = tbl.rows[1].cells[1].innerHTML;

for (j=1; j < len;j++){
//check the value in each row of column 2
var m = tbl.rows[j].cells[1].innerHTML;

if(m!=rowHead || j==1){
rowHead=m;
tbl.rows[j].cells[0].innerHTML = link;
tbl.rows[j].style.background = "#CCFF99";
}
else
tbl.rows[j].style.display = "none";
}
}

window.onload=collapseRows;

Let me briefly explain what the script does. When a page has loaded, the collapseRows function is called. It looks for a table on the page with an id named 'expandable'. If such a table is found, a reference to the table is stored in a variable tbl, and the number of rows in the table is stored in a variable len.

var len = tbl.rows.length;

Then, we create a variable that holds an html link that will call the toggleSection function when linked. The function parameter will contain a reference to the link itself. We using the this keyword here.

var link = '<a href="#" onclick="toggleSection(this);return false;">+ </a> ';

The variable rowHead in the next statement will contain the text in the second column of the first row(not counting the table head). In this table it is January.

var rowHead = tbl.rows[1].cells[1].innerHTML;

The next piece of the code loops through each row, and if the text in the second column contains repeating information, it hides that row. Also, it assigns a different color to the first row with non-duplicate text.

for (j=1; j < len;j++){
var m = tbl.rows[j].cells[1].innerHTML;
if(m!=rowHead || j==1){
rowHead=m;
tbl.rows[j].cells[0].innerHTML = link;
tbl.rows[j].style.background = "#CCFF99";
}
else
tbl.rows[j].style.display = "none";
}

The next function, toggleSection, hides or collapses rows with duplicate months. As a parameter, the function accepts a reference to the link that calls the function. Using the link reference, we get a reference to the containing table cell, row, and then the row index for the cell:

var td = lnk.parentNode;
var tr = getParent(td, 'tr');
var rowIndex = tr.rowIndex;

We obtain text in the second column of that row (January or February, in this example):

var rowHead=table.rows[rowIndex].cells[1].innerHTML;

Next, we switch the text of the link from plus to minus or vice versa.

lnk.innerHTML =(lnk.innerHTML == "+")?"-":"+";

Then, we prepare a style to be used for the next rows.

vStyle =(tbl.rows[rowIndex+1].style.display=='none')?'':'none';

Then, we loop through the table, and if the text in the second column of each row is the same as the text in the same column of the row that contains the link, we hide or show that row depending on its initial state.

for(var i = rowIndex+1; i < len;i++){
if (table.rows[i].cells[1].innerHTML==rowHead){
table.rows[i].style.display= vStyle;
}

We also hide the repeating text in the second column:

table.rows[i].cells[1].style.visibility="hidden";

Don't forget, the table must contain an empty first column to hold a plus or minus sign and have an id named 'expandable'.

How to Change HTML Table Cell Value

First, we need to get a reference to a table cell value.

var table = document.getElementById('myTableId');

An HTMLTableElement has a rows property that refers to the table rows collection. An HTMLTableRowElement has a cells property that refers to the row cells collection.

With this information at hand it is easy to get a reference to any cell.

Let's say, we need to refer to the first column of the first row.

Since the collection index starts at 0 we can get this reference using the following code:

var cell = table.rows[0].cells[0];

The cell variable now refers to the cell in the first column and first row.
The data in a table cell is represented by a text node. We can get a reference to it by using the firstChild property of an HTMLElement.

We obtain a reference to the text node value by using its data property.

var value = cell.firstChild.data;

Now it is easy to change the text in a table cell:

cell.firstChild.data = 'my new text';

Change table cell value automatically


To change table cell value automatically we must assign an event handler to the cell onblur event.