Wednesday, September 16, 2009

Parameterize Your SQL

Just read this from Antonio Cangiano's blog:

Parameterized queries are therefore efficient and go a long way towards preventing SQL injection attacks in your applications. They have virtually no downside.

Newbie developers often ignore the existence of this feature and end up irritating seasoned DBAs who have to deal with the consequences of their incompetence.


And all this time I've been avoiding parameterized queries because I thought creating prepared statements was less efficient. Turns out they get cached though. Doh!

After reading these brief articles, here and here, I vow to change my ways.

Friday, April 10, 2009

Dynamic DOM Node Element Creation in JavaScript

Lately I've been maintaining and upgrading a browser-based web app that consists mostly of JavaScript files. There's a lot of dynamic creation of DOM elements and I was getting tired of looking at line after line like this:

var elem=document.createElement('div');
elem.id = "mydiv";
elem['className'] = "padded label";
elem.appendChild(document.createTextNode("Customer Information "));
contentDiv.appendChild(elem);


That's just to create a single text node inside a div.

Or this kind of thing:

div.innerHTML="<b class="'smallBold'">Line Info:</b><br />" +
"<table class="'smallLeftTable'">" +
"<tr><th>Property</th>" + headers + "</tr>" +
"<tr><td>Site:</td>" + siteHTML + "</tr>" +
"<tr><td>Route:</td>" + routeHTML + "</tr>" +
"<tr><td>Pair #:</td>" + pairNumberHTML + "</tr>" +
"<tr><td>Pair Type:</td>" + pairTypeHTML + "</tr>" +
"<tr><td>Status:</td>" + statusHTML + "</tr>" +
"</table>";


That's even worse, I think. There's something buried deep within my psyche that makes me loathe using innerHTML.

So I decided I needed a slicker way to create DOM elements in my code. I remember reading that someone somewhere had created a function named $E()--in the spirit of prototype.js--for creating elements. I couldn't find that one though, so I wrote my own version of $E().

The HTML file below contains the code for $E() and some example usage, but it boils down to specifying the type of element to create, all of its attributes, and all of its child nodes in a single call. $E() then recursively builds the whole tree. The div with text, above, would be created like this:


var elem = $E('div', {id:"mydiv", className:"padded label"}, "Customer Information");


Remember when specifying a css class as an attribute, don't use the keyword "class". Use "className" instead.

Here's the HTML file containing $E(), its documentation, and examples. Go ahead and copy and paste it to a file on your system, pull it up in a browser, and start modifying and playing with it. I think you'll like how much smaller your .js files can be using $E().

<html>
<head><title>$E() Test</title>
<style type="text/css">
table.styled {
border-collapse: collapse;
background-color: yellow;
}
</style>
<head>
<body>

<!--
Here's the example table, created the old-fashioned way.
-->
<table id="table1" border="1">
<caption>Cups of coffee consumed by each senator</caption>
<tr>
<th>Name</th>
<th>Cups</th>
<th>Type of Coffee</th>
<th>Sugar?</th>
<tr>
<td>T. Sexton</td>
<td>10</td>
<td>Espresso</td>
<td>No</td>
<tr>
<td>J. Dinnen</td>
<td>5</td>
<td>Decaf</td>
<td>Yes</td>
</table>
<br/>
<br/>


<!--
This div is a root for the dynamically created tables.
-->
<div id="mydiv">
</div>


<!--
The rest of this file is the script that runs our demonstration.
-->
<script language="javascript">

//
// Here it is: $E()!
//
// Returns a DOM Element or an entire tree of DOM Elements.
// Usage:
// $E(text) -> Text node element
// $E(Element) -> Element
// $E(tag, attributes, children) -> Tree of DOM Elements
// Where:
// text = string
// Element = DOM Element
// tag = String -- The type of Element, e.g. "div"
// attributes = object -- The attributes of the Element, e.g. {id:"mydiv", height:"50px"}
// children = text | elem | list
// Where:
// text = String -- Appended as a Text node.
// elem = Element -- Appended
// list = Array -- A list of Strings or Elements (or both), appended
//
function $E() {
if (arguments.length == 1) {
if (typeof arguments[0] === 'string') {
return document.createTextNode(arguments[0]);
} else {
return arguments[0];
}
}
var elem = document.createElement(arguments[0]);
if (arguments[1]) {
for (key in arguments[1]) {
elem[key] = arguments[1][key];
}
}
if (arguments[2]) {
if (arguments[2] instanceof Array) {
for (var i = 0; i < arguments[2].length; i++) {
elem.appendChild($E(arguments[2][i]));
}
} else {
elem.appendChild($E(arguments[2]));
}
}
return elem;
}


//
// Begin the demonstration by getting a handle to the root
// div we created above.
//
var mydiv = document.getElementById("mydiv");


//
// This demonstrates coding the same table as above using $E()
// and nested calls to $E().
//
mydiv.appendChild(
$E("table", {id:"table2", border:"1"},
[$E("caption", null, "Same table using $E()"),
$E("tr", {}, [$E("th", null, "Name"),
$E("th", {}, "Cups"),
$E("th", {}, "Type of Coffee"),
$E("th", {}, "Sugar?")
]
),
$E("tr", {}, [$E("td", {}, "T. Sexton"),
$E("td", {}, "10"),
$E("td", {}, "Espresso"),
$E("td", {}, "No")
]
),
$E("tr", {}, [$E("td", {}, "J. Dinnen"),
$E("td", {}, "5"),
$E("td", {}, ["Decaf"]),
$E("td", {}, "Yes")
]
)
]));

// A little white space for looks.
mydiv.appendChild($E("br", {}, null));
mydiv.appendChild($E("br", null, []));


//
// Now the good stuff.
// Dynamically generate a table filled with data from an array.
//

//
// The data
//
data = [["T. Sexton", "10", "Espresso", "No"],
["J. Dinnen", "5", "Decaf", "Yes"],
["A. Johnson", "3", "Latte", "Yes"],
["B. Brown", "1", "Cappucino", "No"],
["C. Jones", "7", "Mocha", "Yes"]];

//
// Initialize the table
// Notice we use "className" (not "class") to set css class.
//
var table = $E("table", {id:"table2", border:"1", className:"styled"},
[$E("caption", null, "Same table using data from an array, "+
"with a few more rows and some style."),
$E("tr", {}, [$E("th", null, "Name"),
$E("th", {}, "Cups"),
$E("th", {}, "Type of Coffee"),
$E("th", {}, "Sugar?")
]
)]);

//
// Populate the table from our data array
//
for (var i = 0; i < data.length; i++) {
var tr = $E("tr", null, null);
for (var j = 0; j < data[i].length; j++) {
tr.appendChild($E("td", null, data[i][j]));
}
table.appendChild(tr);
}

//
// Append the newly created table to mydiv
//
mydiv.appendChild(table);

// A little more white space.
mydiv.appendChild($E("br", null, null));
mydiv.appendChild($E("br", null, null));

</script>
</body>
</html>