Category Archives: DHTML

DHTML: removeChild or div.innerHTML?

I ended up with a strange issue today, a difference in behavior between IE and FF (tell me something new huh?).

I have some dom nodes and they are dynamically inserted into a popup div as needed. So, before they are inserted, I first need to clear the popup div itself. I was doming (made a typo for doing but thought this is appropriate as well, “doming”) like

div.innerHTML = ”;
// add the existing nodes by context

This worked in Firefox. In IE, it did work, but subsequent popups started not showing the inner nodes being added. So, I changed the above to

for(var i=div.childNodes.length-1;i>=0;i–) div.removeChild(div.childNodes[i]);
// add the existing nodes by context

And this started working. So, it looks like when div.innerHTML is set to blank, or may be some other value for that matter, the existing nodes in the div and their content is being cleared up by IE, while firefox doesn’t clear up the contained nodes.

1 Comment

Filed under DHTML, javascript

Bringing A Marker To The Top

In maps and charts, where there are several markers, there is a likelihood of a overlap depending on how dense the data is. In such cases, it would be good to be able to bring the marker that has been selected using the mouse to the top and display the details and push the rest of the neighboring points to the bottom. And then when a mouse is placed over one of those neighboring points, then the current point should go down and the other point should come up.

So, how to achieve this in HTML using Javascript? Below is a way to do this.

Say each marker is a div element. You can do the following. First have a depth variable.

var depth = 1001;

Now, have the following code for the div.

div.onmouseover = function(event) { div.style.zIndex = depth++; }

That’s it! What this does is, every time the mouse is placed over a div, it sets it’s depth to be one more than the current maximum depth ensuring that the element is the top-most element. Isn’t this simple and elegant?

Leave a comment

Filed under DHTML, javascript, Maps

JavaScript Performance – Incremental Asynchronous Processing

I have an application where the hierarchical data is displayed as a table and I need to provide the ability to expand and collapse the nodes (I explained how this can be done in my Nested TBODYs post). With large data sets this had a lot of problem and Netscape displays the standard dialog about stop/continue the script. After a bit of research, it turned out that using the setTimeout method, the long running code can be made asynchronous.

So, I thought that’s not a big deal. Just call the function in setTimeout. After doing that, I still had the same problem. Then, it appears that even with setTimeout, the code shouldn’t be running for too long or otherwise I would end up with the same stop/continue dialog.

Then it turns out, the solution is to keep calling the setTimeout multiple times and each time doing only a small part of the computation. Now, how the heck can this be done when you have a big loop? Below are the steps to do that.

Say you had code like


for(var i=0;i<rows.length;i++) {
... // some logic
}

Change this to


var i=0;
function dosomething() {
var count = 0;
for(;i<rows.length;i++) {
... // original logic
count++;
if(count == 10) // change this to an appropriate number
break;
}
if(i<rows.length)
setTimeout(dosomething,0);
}

This is pretty much it!

Now, say you want to do something at the end of such long logic in loop. How can this be done? You can do this by using a callback function. So, the above code would be changed to


var i=0;

function dosomething(callbackf) {
var count = 0;
for(;i<rows.length;i++) {
... // original logic
count++;
if(count == 10) // change this to an appropriate number
break;
}
if(i<rows.length)
setTimeout(dosomething,0);
else if(callbackf) callbackf();
}

That’s it, now at the end of this incremental asynchronous processing, you get a hook to do some additional logic. Infact, you can keep nesting these incremental-asynchronous computations each of which calling at the end of the other.

Couple of things to note:

1. The dosomething should be a function defined within the context of another function and the loop variable. This essentially creates a closure for the loop variable. Defining the function as a top level function will not work.
2. In my specific case, I had defined the dosomething function twice, once in each part of the if-else statement. For some reason, this didn’t work in IE. Giving a different name for each case worked though.
3. In the above code, where the count is incremented, if you have logic that skips doing anything for certain increments of the loop variable, i, then don’t increment the count variable. For example, in my hierarchical data expansion/collapse functionality, there are times where the rows are already hidden and I don’t have to hide them again. This improves the speed a bit more as the number of chunks of incremental processing are optimized.

2 Comments

Filed under DHTML, javascript

Nested TBODYs

The quick answer is, this is not possible. But continue to read on a possible workaround.

As per the HTML 4.01 tables specification, a tbody consists of only TRs. So, that essentially means, it’s not possible to have nested TBODYs. Ofcourse, a cell in a row can contain a table that can contain a TBODY, but we are not talking about that type of nesting, are we?

Taking a step back, what’s the need for nested TBODYs? I have a hierarchical data that is displayed as a table and to provide the ability to expand and collapse, a quick temptation is to make the child nodes of each parent node to be put into a tbody and just hide/show that tbody element alone. Now, due to the hierarchical nature, a child node itself will need to be created as a tbody to capture it’s own children. So, this is where the need for a nested tbody arises.

So, after checking the above mentioned specification that it’s not possible to nest tbodys, I achieved the above required expand/collapse functionality using TRs itself. The trick here is to make use of the ID attribute and specify a unique ID for each TR such that the TR elements of the child nodes contain the IDs which contain the ID of the parent element in them as a prefix. For example, if the parent has an id of ‘0’, then the child 1 can contain ‘0/0’, child 2 can contain ‘0/1’ and child of child 1 can contain ‘0/0/0’ and so on. With this approach, when the user is trying to expand/collapse a node, I can loop through all the TRs of the table and identify those that have a prefix same as the id of the node being expanded/collapsed and then hide/show those rows accordingly. I tried this idea and it worked without any problems.

6 Comments

Filed under DHTML, javascript

HTML Table Sorting Using JavaScript

One of the most common actions when viewing data in a tabular format is to be able to sort. With DHTML and JavaScript, it’s possible to sort the data on the clientside. This avoid unnecessary roundtrip to the server and improves the usability. There are a few javascript libraries that provide the sorting capability with minimal edits to the html. However, if you want to have a total control over the sorting, for features such as, sorting a column sorts against data that is different than what’s visible (for example, data is displayed as percentages while the sorting is done without the % symbol, data is displayed as yyyy/mm/dd but internally there is a date object corresponding to what is displayed), then more control is required on sorting the data. Below is a snippet of code for doing this.


function DataRow(data) {
this.data = data; // data is itself an array or other object that contains data
this.row = null;
}

var data = new Array();
// here generate/write javascript to store the rows and their data, for example,
// data[data.length] = new DataRow(new Array(1,2,3));

var table = document.getElementById('data'); // assuming there is no THEADER
if(table.firstChild.nodeName == 'TBODY') table = table.firstChild;
var rows = table.getElementsByTagName('TR');
for(var i=1;i<rows.length;i++) // assuming header is also stored as a row
data[i].row = row[i];

function sortTable(event,col) {
var header = table.firstChild; // storing both heading and data in tbody.
while(table.firstChild) table.removeChild(table.lastChild);
table.appendChild(header);
data.sort(function(a,b) { return a.data[col] - b.data[col]; });
// you can have more complex logic based on the data and requirements
for(var i=0;i<data.length;i++)
table.appendChild(data[i]);
}

Next, it’s a matter of pluging in the sortTable(event,col) call in the onclick of the header.

The key idea here is to be able to keep the data and the related UI element (the row), together as an object and do sorting on those objects.

Leave a comment

Filed under DHTML, javascript

innerHTML and SCRIPT tags

I have a requirement where I get some HTML snippet through Ajax request and then update a div area. So far so good. The HTML snippet needed to have some javascript (so that I could display a date as per the user’s timezone). That’s when the trouble started.

After a bit of research, came to the conclusion that

div.innerHTML = some-string-containing-script-tags;

doesn’t work. Some one mentioned about using <\/script> instead of </script> but that didn’t work for me though there was a reply to the suggestion that it worked! Then there is an interesting hack on how to achieve the same. While this is a cool hack, I didn’t wanted to do it.

So, by trail and error, in Firefox 2.0, it seemed to work by doing the following.

var div = document.createElement('div');
div.innerHTML = htmlFromAjaxResponse;
var children = div.childNodes;
actualDivToBeUpdated.innerHTML = "";
for(var i=0;i<children.length;i++)
actualDivToBeUpdated.appendChild(children[i]);

This worked in Firefox 2.0. The script in the original response HTML did get executed. (note though not to use document.write in the script. Instead, you have to manipulate the DOM).

The same technique didn’t work in IE though.

Update: As per microsoft making a script tag marked with DEFER attribute makes it possible to execute script by setting it through innerHTML. I tried and it worked. However, I now have the problem that the DOM node that’s inserted using the innerHTML doesn’t seem to be available by the time the script is executing even though the script is placed after the dom node.

Update 2: Finally got it working on both Firefox and IE. The problem with the DOM manipulation mentioned above is, in case of IE, after marking the script to DEFER, it is executed for the DIV element whose innerHTML is set. Since I am creating the DIV brand new, it’s not yet within the DOM, so trying to use getElementById in the script from the document is causing the problem. So, I had to introduce a dummy DIV element in the initial document and then it worked. However, for Firefox, the dummy element idea doesn’t work. It has to be a new element to create the DOM. Since that DOM is copied to the actual node as per the code shown above, at that time the script gets executed fine. So, I ended up writing browser specific code, but finally it seems to work for both browsers.

21 Comments

Filed under AJAX, DHTML, javascript

Script.aculo.us Effects on a Tag/Keyword Cloud

Script.aculo.us is one of the popular Web 2.0 javascript library which goes with the theme of “it’s about user interface baby!”

And Tag Cloud is also a Web 2.0 concept.

So, what if we combine these two together? You get Script.aculo.us effect on a Tag Cloud. That’s exactly what the ToCloud Keyword Cloud Generator has done. Here are a few examples.

Plusate Effect on My Blog

Grow Effect on Amazon Homepage

Shake Effect on MySpace.com

BlindDown Effect on Yahoo!

Leave a comment

Filed under DHTML, javascript, keyword cloud, script.aculo.us, tag cloud, Web 2.0, word cloud