I'll recap our telco discush for anyone else following this thread.
@ handling an unknown number of rows in a table being viewed/edited by the user:
The best way that I have found is to rely on the DOM as your storage and "stack navigation" mechanism. In other words, why put something into variables if the DOM is, in fact, one big stack waiting for you to walk it?
If I have a really complicated table of information that I want to display to the user, I have really 3 choices: A) build a whole new page and ship it out, B) AJAX back the data alone and build the HTML client side or C) build the HTML server side and AJAX it back and display it client side.
Obviously, A is unsuitable for this discussion because we want an AJAX app.
B is reasonable, and I've done it quite a bit. However, depending on the complexity of the table or thing you are building, this can weigh heavy on local processing time. Also, you just handed the perception of the application's snappiness to the browser's implementation of JS. There are also idiosyncrasies you'll need to deal with when building tables and multiple browsers. This is why I built my tableManager class, which allows me to programmatically build a table in JS that works for any browser. All that said, if I pass back 500 rows and build 10 cells per row, I've got a lot of client-side processing to do and the app will feel sluggish
at best.
C is the right choice in this case - build the HTML serverside and simply node.innerHTML = (the packet) and kerpow, client application updated. Snappy, pretty. However, there are some problems with this: the original page has no idea about what data is now sitting in the innerHTML of that target node. This is where I use the dom. Consider:
<table>
<tr id="row_id_12345">
<td>Some Data</td>
<td>Some More Data</td>
<td><input type="button" value="Click Me To Edit This Row" onClick="editRow(this)"></td>
</tr>
<tr id="row_id_45678">
<td>Some Data</td>
<td>Some More Data</td>
<td><input type="button" value="Click Me To Edit This Row" onClick="editRow(this)"></td>
</tr>
</table>
Now consider that I have a handling function:
function editRow(sender)
{
var target = sender;
while(target.nodeName != 'TR') target = target.parentNode;
alert('The ID I'm looking for is: ' + target.id;
}
So what I'm doing here, is when I created the HTML in PHP I made the row have the unique database ID of the actual DB row I'm editing. The button calls a function that <we> already know about - it was sent with the original page load, called "editRow." It calls that function with a parameter of itself: "this." The handling function then receives the node that called it and walks up the DOM tree until it finds a TR (row) node, at which point I know that I've found what I am looking for
(Note: Of course this is not exactly how I do it because I can make this WAY more efficient, but I've written it this way for readability). In this way, the DOM has become one big blob of data that I can navigate and retrieve from at will. So I now no longer need to know about anything that's in the innerHTML, because I can get it when I need it. Follow?
Just out of curiousity, when you build an ajax site, what is the process of creation?
Normally, when I build a traditional client/server/refreshall application, I build out the visual framework first, then plug in the functionality. This is partly a result of my project types, which are usually very plan-on-the-fly.
Does that same philosophy make sense in an ajax app?
Absolutely. The methods for building a good application are the same, regardless of comm mechanics under the hood. I choose to ship out everything that the client will need to know with the original page load, because the surfer is already expecting a delay - and then ship only what is really necessary during application run time. This offers a problem: if you have lots and lots of code to ship out to the client, how do you manage it (from a developer's perspective)?
The phpMyIDE app is an example of how I choose to manage it. At the moment a surfer calls for the app, it does not exist. The main.php includes all of the modules that should be used to construct it. These modules all contribute to a wide variety of string arrays: CSS I will need to include, initialization JS, functional JS, HTML and so forth. The main routine, having included all of the modules, will now have a big'ol array filled with all of the stuff that should be in the output. I'll implode the CSS array into a single string, then put that in the header of the output: I'll implode the functional JS array and include that in the header: I'll implode the initialization JS and include that in the body of the output: I'll implode the HTML into a string and include that in the body of the output and so on and so forth.
In this way, I can look at code JUST for <this> module at any given time and I can keep my brains unconfused (a more and more dicey proposition as I age LOL) - and I can include/exclude modules with a single comment character (ie., in the main.php I simply DONT include a particular module and nothing about it will be included in the output to the surfer). Hope that makes sense... that one took quite a while for me to figure out and implement.
The example is a todo list.
You have 10 items in your list.
you could update an item.
you could delete an item, removing its row from the table
you could add an item, adding a row to the table
you could have no items, meaning no table yet exists, though i guess it could have a blank row.
do I build it out in HTML then "apply" an ajax layer to it?
The temptation here is to "fire and forget" ajax calls that send a DB update but do the client-side GUI work without interacting with the DB or waiting for it. This looks good on paper, but you are setting yourself up to be out of sync with the server, consider this: let's say someone adds 3 todos to the system. The GUI is updated and all looks good. But unbeknownst to them, their cable modem is down and they have no comms with the server. They think they've added todos but the DB has done nothing.
My personal fix is to always respond with this on success (for a simple update like request) : echo json_encode(array('OK')); then on the client side I'll do this:
function handleUpdate(sender)
{
try {
var arr = eval('(' + sender.lastResponse + ')');
} catch (e) {
alert('Error: ' + e.message);
}
if (arr[0] != 'OK')
alert("Warning: " sender.lastResponse);
}
Very quickly, I know if the server has done what I asked. The reason I did it this way, is that if MySQL pops back something like "Warning: $res is not a valid result set" or something, eval will bomb and presto, I get my error from PHP. This is a vital trick, because debugging AJAX apps is another thing that took me quite a while to get my arms around so that I could be efficient. In fact, it sucks horribly at first.
this is way out of my comfort zone. But only this first step. after that its a non-thing. I am just stuck on the how-the-hell-to-start step.
You'll do well because at the core it works the way you think. It's a bastard to start out tho, believe me I understand. Hope all this helps.
/p