The Cache: Technology Expert's Forum
 
*
Welcome, Guest. Please login or register. September 18, 2019, 10:44:29 AM

Login with username, password and session length


Pages: [1]
  Print  
Author Topic: Advanced Javascript or Walking the DOM for Fun And Profit!  (Read 5260 times)
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« on: October 05, 2007, 11:14:38 AM »

This is actually a continuation of a long-dead thread I started here:
http://www.perkiset.org/forum/ajax/the_argument_against_ajax-t155.0.html
relating to why some of the focus on XML in Ajax is bad.

Before I start, a quick question: What is a variable?
A variable is simply a name for a place in memory that I wish to hold onto some value. The variable name itself, is simply a reference in a hash table for where that memory resides. So in other words, a variable name is a way to get to the values that I am hanging on to.

In the mid 80s while coding in Clipper, I thought to myself, why do I always need to create a variable to hang on to things if I can see them on the screen? If it’s <there> and I can get to it, then why take up more memory to store it elsewhere? (The problem was that Clipper was a memory hog and the 640K limit was rapidly used up). So I wrote a routine that allowed to me to reference items on the screen in a way that was similar to my variables and Voila! I saved a boodle of memory.

The memory storage requirements are not as big today, but processing in Javascript particularly can be. When I want my Ajax apps to snap, the less processing I can put on each side of the call the better. So if I can avoid taking data at the server, converting it into XML, sending it back to the surfer, re-livening the send text into XML, extract the values I need into arrays for later retrieval, then dynamically construct HTML I’d really like to. My premise: PHP is already processing data into text – make that text HTML rather than XML and send it back to the browser, which can display that HTML lickety split. Consider: if you have a bunch of tabular data you are presenting the user, do they really need access to every single piece of data at once, or are they more likely to edit/touch one piece? At least, one piece at a time…

Example Application
In my back office suite, one of the applications I provide for my users is a “Return Email Cleaner.” This handy little app looks at inbound emails returning from a blast and compares them against a set of data to see if there is an automated thing that can be done ie., if I see a “Status 5.0.0” in a returned email and I see that there is a recognizable address in the content, I know that the address is no longer valid, and at the least, the address should be unsubscribed. This system allows users to add/edit as many rules (I call them “markers”) as they want. Of course the reality is that I do the marker work for them, but they get to see it and it’s impressive. And billable Wink

Here is a snippet of a munged screenshot of the app in action:
« Last Edit: October 05, 2007, 11:20:52 AM by perkiset » Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #1 on: October 05, 2007, 11:15:16 AM »

Here's the image:


* REVExample.jpg (57.27 KB, 600x239 - viewed 652 times.)
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #2 on: October 05, 2007, 11:19:55 AM »

This is a dynamic web page that is all Ajaxy. When you click on an Active checkbox, it sends the request immediately up to the server and it’s immediately activated/deactivated. When you edit a field (as you can see on line 4) new icons appear for save and revert. As you can also probably see here, you can add or delete as many items as you want pretty effortlessly.

Here’s what I do. When a user clicks on the “markers” radio button (center bottom) I display a div that is empty. I throw a request at my server for all the current markers. The PHP at the server creates ready-to-go HTML. Here is what a single row looks like:

Code:
<tr valign="middle" class="arial s11 normal bk" onMouseOver="this.style.cursor: pointer;">
<td align="center">
<span style="display: none" comment="id">1</span>
<span style="display: none" comment="dirty">0</span>
<span style="display: none" comment="caption">Status 5.0.0</span>
<span style="display: none" comment="marker">Status 5\.0\.0</span>
<span style="display: none" comment="action">2</span>
<input type="checkbox" CHECKED onClick="updateActive(this)">
</td>
<td><input type="text" style="width: 150px" value="Status 5.0.0" onKeypress="makeDirty(this)"></td>
<td><input type="text" style="width: 150px" value="Status 5\.0\.0" onKeypress="makeDirty(this)"></td>
<td>
<select size="1" onChange="makeDirty(this)">
<option value="1">Delete Contact Record</option>
<option value="2" SELECTED>Delete on empty else unsubscribe</option>
<option value="3">Change status to Needs Attention</option>
<option value="4">Remove message, do nothing</option>
<option value="5">Unsubscribe record</option>
</select>
</td>
<td align="center"><img src="/graphics/dot_clear.gif" height="16" width="16" onClick="doSave(this)"></td>
<td align="center"><img src="/graphics/dot_clear.gif" height="16" width="16" onClick="doRevert(this)"></td>
<td align="center"><img src="/graphics/icon_delete.gif" height="16" width="16" onClick="doDelete(this)"></td>
</tr>

As you can see, by sending back complete and ready-to-display HTML, the ajax call simply needs to do a document.getElementById(‘theDiv’).innerHTML = kind of thing… I only need to modify what the surfer is looking at, I don’t need to do any processing at all. This is about as fast as JS and a server call can get. But note the incredibly important event drivers, like onClick: updateActive(this) – that’s the key to pretty much the key to what comes next.

Responding to events
OK, so the user clicks on the active checkbox of a row… what to do? Well, since the function call sent the this reference in it, I have a handle to the node that sent me the event. My personal protocol is to call that parameter “sender” because it makes sense to me.

Code:
function onActive(sender)
{
}

Now I have an event handler that will respond to any “active” checkbox that the user clicks on. But the “id” field that I desperately need to make my call to the server is in a completely different place… how do I get it?

Code:
function onActive(sender)
{
node = sender;
while (node.nodeName != ‘TR’) { node = node.parentNode; }
}

This little snippet will now take the “sent” node, and walk up the DOM tree (or out of the tree, depending on how you look at it) towards the root until the name of the node is TR… or a Table Row! Look again at the demo HTML row: it is clear that the sender is in a cell, which is of course in a row of a table.

The next step is to grab all of the spans that live on the tree under the current row… again by my own personal design, I try to choose either inputs for display and spans for data, or spans for display and inputs for data – this just makes life a little easier. The magic function is getElementsByTagName (note, Elements)

Code:
function onActive(sender)
{
node = sender;
while (node.nodeName != ‘TR’) { node = node.parentNode; }
var spans = node.getElementsByTagName(‘SPAN’);
var id = spans[0].innerHTML;
alert(id);
}

As you can see, by asking the ROW node for children under it of the SPAN persuasion, I get everything on the tree underneath it that I want… which is the data I’ve been looking for. I can then reference the ID of <this> row and send off an Ajax request to Activate/Deactivate the marker with an id of <that id>.

One more time, with feeling:
* The Active checkbox is clicked for a row
* The checkbox sends an onClick event to the function onActive, with the parameter (this) (reference to the node).
* The onActive function hears the function call with the reference to the DOM node (sender)
* The "node" variable is set to the sender parameter
* Loop: while the "node" variable's name is not TR (table row) I ask for <it's> parent node.
   * The first step is to the TD
   * The second step puts me at the TR
* I ask the ROW node for all elements underneath it that are a SPAN
* Since  know the order of the SPANS under this row, I know that span[0] will have the ID value I'm looking for
* In this example, I simply do an ALERT with the value, but in the real application, I shoot of an AJAX request to the database that updates the marker with ID (theID).


Note: Some would argue that I could have placed the ID right into the dynamically written javascript, rather than doing it this way and you’re right: I could have. But many other functions in this example require the methodology that I just described, so in the interest of future readability I’ve done all functions identically rather than using a different method for each feature of the application


Why is this so important?
Well, in a clear cut example as you see here, it seems to be less important because there are other ways of doing it. But consider now: the user adds several and deletes several items from <somewhere> in that list… now the array management issues (and debugging) start to get really scary. Why do all that, since the DOM is keeping it “visually sorted” for my surfer, and I can “Ask The DOM” for the values?

And back to the original question, What is a variable?
Thinking in this way, the DOM can become just another variable heap for you – and the method for “getting what you want to hang on to” is just a little different than if you use the more traditional variable name. Is this more processing intensive than just using a variable name? Of course! But it is trivially more intensive, and more importantly, it reduces an incredible amount of processing time that I’d need to go through if I was maintaining parallel arrays that managed the data.

Looking forward to your comments,
/p
« Last Edit: October 05, 2007, 11:33:58 AM by perkiset » Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
arms
Expert
****
Offline Offline

Posts: 235



View Profile
« Reply #3 on: October 05, 2007, 04:49:37 PM »

imo xml is good for web services. almost everywhere else it's being overused.
returning html is the way to go. xml just adds an unnecessary layer.
Logged
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #4 on: October 05, 2007, 05:02:46 PM »

Short, sweet, I like it and agree: XML is WAY overused - HTML is just fine, at least when talking to a surfer/client. I still use it in many places for inter-process comms where I have disparate hardware/OS etc... although I am beginning to use serialized PHP arrays in certain spots as well, since my backend is almost entirely PHP now.
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
freedom1972
Rookie
**
Offline Offline

Posts: 17


View Profile
« Reply #5 on: October 06, 2007, 10:42:14 AM »

The discussion is a bit beyond my current web app skills, but what I like the most about the idea is the flexiibilty in thinking about what the DOM can do, what variables are, etc.  IMHO it is thinking along these lines that leads to new devleopments in languages, improved strucutual frameworks in existing languages, etc. What I take away from it is simply this: expand your mind!
Logged

No links in signatures please
Pages: [1]
  Print  
 
Jump to:  

Perkiset's Place Home   Best of The Cache   phpMyIDE: MySQL Stored Procedures, Functions & Triggers
Politics @ Perkiset's   Pinkhat's Perspective   
cache
mart
coder
programmers
ajax
php
javascript
Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks


Valid XHTML 1.0! Valid CSS!