- Usual Background Rant
- The Basic Object
- Strategies for Non-Conforming Data
Strategies for Non-Conforming Data
This discussion must begin by asking, "Why do we care?" And that's the voice of the untapped potential that is current Web development. Amid the fancy graphics, lackadaisical programming standards, and excuses about competing browsers, the previously high expectations of the software customer have been whittled to a nub.
In most cases, it suffices to let the browser simply wrap text around a small table, or set the table width to 100% and let the user scroll as the <DIV> expands. But what about when neither of those approaches is adequate? You want to exceed the customer's expectations and distinguish your offeringand, above all, it's a challenge.
The most intuitive answer to this problem is to detect the dimensions of the table and compare them to the dimensions of the <DIV>. Once the numbers are known, provide Next and Previous buttons for changing the data if it exceeds the bounds.
To facilitate this function, there are three event "prototypes" at the top of the JavaScript file. Remember, these are just skeleton functions, to be overridden if additional functionality is desired.
function OnHTMLDataGridRowSelect(rowNumber) {} function OnHTMLDataGridDataChange() {}
If we don't want to implement one or all of these behaviors, the prototypes make sure that no error will be thrown when the event occurs and the object calls the appropriate function. In my first attempt only two events are supported, but certainly more grid events could be seen, just as more behaviors could be defined.
Whenever a row is added or deleted, or an edit is submitted, the OnHTMLDataGridDataChange event is fired. From that point, the default redraw method may be called to refresh the current page (or any other action we choose). For instance, in the included HTML page, a set of input boxes is provided for creating a new row for display in the table. As a slight variation, when a row is added the page with the new row is displayed, as follows:
"<input id=currentRow" + x2 + " value=\"" + unescape(arData[x2]) + "\">";
Basic HTML constructed with JavaScript. The rows are distinguished by the position in the table, and the values are un-escaped to display properly. Just to make things a little more straightforward, we add an Update button that commits the changes. This all takes place without a single call to the server. If these changes are to be stored in a database or communicated to another part of the system, that's also possible. Either submit the changes to a hidden frame within the event function, or make a wholesale submission when the user is finished with the page. But there's no reason for the user to suffer page refreshes just to perform the edits.
An important key to event-based behavior in an object like this is the fact that JavaScript has the novelyet dangerously usefultendency of only remembering the last thing it's told. On the other hand, it will remember just about anything you tell it. The existence of the event functions in the JS file means that the events don't need to be implemented. On the other hand, because the code in the HMTL file is always interpreted following the code in any include files, simply giving a function on the page the same name will override the functionality, as follows:
function OnHTMLDataGridDataChange() { document.all["mandiv"].innerHTML = testData.objHTML(); } function OnHTMLDataGridRowSelect(arData, rowNumber) { testData.editRow(arData, rowNumber); }
In the case of OnHTMLDataGridDataChange, the grid is simply redrawn. For OnHTMLDataGridRowSelect, however, the integrated editRow functionality is invoked, and the table is redrawn with the row selected available for changes. It's a useful, if clunky, implementation that will be improved.
Overriding functions is one need for this behavior; the prototype keyword is another. This is not to be confused with my version of event implementation. This is what allows one of the final pieces in the OOD playbook to be implemented in JavaScript. The code is as follows:
HTMLDataGrid.prototype.reportValue = reportGridValue; function reportGridValue(x, y) { var rowVal = this.arrayData[x]; alert(rowVal[y]); }
In the HTML file, once the HTMLDataGrid object has been included, say you just really need a method to display the value in the grid given the x and y coordinates. If it's not in the object, how can it be done? Inheritance, with a twist. Instead of creating a new object that extends the functionality of the parent, you actually modify the object with methods you define later. While knowledge of the object implementation is required to do anything truly useful, source code on the Web is readily available to all.
Actually, I lied about the useful part. If you add the following code to any newly implemented method, the text of the entire object will be displayed without any foreknowledge of the object:
alert(this.constructor.toString());
Don't ask me. It's just something to know.
Now that we've fleshed out the rudimentary details, let's use the next article to turn this object into something worth putting into a storefront or sending to a customer.