
Originally Posted by
mburt
Try this:
Why on Earth did you create your own list-like "element" when ordered lists are already a feature of HTML?
It sets a good example if code samples follow best practice. That includes using a document type declaration...
...and a title element.
<script type="text/javascript">
var i = 2
If you'd used a list, tracking the next list number wouldn't be necessary, and this variable would become redundant.
Why not the increment (post- or pre-) operator (++i)?
var newitem = document.createElement("SPAN")
You should determine whether the createElement method is supported before calling it. You should also check the return value as not all browsers are equally dynamic; some will only create certain elements.
var text = document.createTextNode(i+". "+inputfld.value)
Checking for support of the createTextNode method is also a very good idea. The same applies to the appendChild method, below.
list.appendChild(newitem).appendChild(text)
From where did you get object reference for the list variable. I hope you weren't trying to use MSIE's poor habit of introducing elements with id attribute values as global variables. Not all browsers do that (and good for them).
.listitem {
display:block;
Again, this wouldn't have been necessary if you'd just used a list.
Don't use pixel lengths for font sizes, and don't use Verdana if you feel the need to reduce its size. And what's that "ref" all about? A list of font families should end with a generic family (sans-serif, in this case).
As the OP wasn't very specific, I wrote an over-the-top client-side implementation. It attempts to use the XMLHttpRequest object to send the new value to the server after checking that it isn't currently in the list. However, if that fails, or manipulation of the document tree isn't possible, it will fall back to a simple POST submission. If only a client-side implementation is necessary, then the AJAX-related code can simply be replaced with the DOM manipulation code that it would eventually call.
Comparisons with existing list items is performed case-insensitively. Leading and trailing whitespace is removed from any entered values (something that would also need to repeated server-side).
HTML Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Adding to lists.</title>
<script type="text/javascript">
var global = this;
function getRequestObject() {
var object = null;
if ((typeof global.XMLHttpRequest == 'object')
|| (typeof global.XMLHttpRequest == 'function'))
object = new XMLHttpRequest();
else if ((typeof global.createRequest == 'object')
|| (typeof global.createRequest == 'function'))
object = createRequest();
else if (typeof global.ActiveXObject == 'function') {
/*@cc_on @*/
/*@if(@_jscript_version >= 5)
try {
object = new ActiveXObject('Msxml2.XMLHTTP');
} catch(e) {
try {
object = new ActiveXObject('Microsoft.XMLHTTP');
} catch(e) {
object = null;
}
}
@end @*/
}
return object;
}
function validate(form) {
var value = form.elements['new-item'].value.trim(),
list;
if (!value) {
alert('Please enter a name.');
return false;
}
if (document.getElementById && (list = document.getElementById('list'))) {
if (hasMatchingItem(list, value)) {
alert('The value, "' + value + '", already exists.');
return false;
}
return addItem(list, value, form);
}
return true;
}
function addItem(list, value, form) {
var control, httpRequest, item, textNode;
if (document.createElement && document.createTextNode && list.insertBefore
&& form.submit && (httpRequest = getRequestObject())
&& (control = document.getElementById('input'))
&& (item = document.createElement('li')) && item.appendChild
&& (textNode = document.createTextNode(value))) {
var body = 'mode=thick&new-item=' + escape(value);
httpRequest.open('POST', form.action, true);
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
if (httpRequest.status == 204) {
item.appendChild(textNode);
list.insertBefore(item, control);
} else if (httpRequest.status == 409)
alert(httpRequest.responseText);
else form.submit();
control = form
= httpRequest
= item
= list
= textNode
= null;
}
};
httpRequest.setRequestHeader('Content-Length', body.length);
httpRequest.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
httpRequest.send(body);
return false;
}
return true;
}
function hasMatchingItem(list, value) {
if (list.getElementsByTagName) {
var items = list.getElementsByTagName('li');
value = value.toLowerCase();
for (var i = 0; i < items.length - 1; ++i) {
var item = items[i];
if (item.firstChild && (item.firstChild.data.toLowerCase() == value))
return true;
}
}
return false;
}
String.prototype.trim = function() {return String(this).replace(/^\s+|\s+$/g, '');};
</script>
</head>
<body>
<form action="list-handler" method="post" onsubmit="return validate(this);">
<ol id="list">
<li id="input">
<input type="text" name="new-item" value="">
<input type="submit" value="Add">
</li>
</ol>
</form>
</body>
</html>
When the client sends the data transparently, it adds a parameter named "mode" with the value "thick" (as the browser is attempting to do much of the work, it's acting as a thick client). This parameter is absent when the server is expected to return a new document containing the added item.
In "thick-client" mode, there are only two responses expected from the server: 204 and 409. The 204 No Content response indicates success; the data has been stored by the server and there were no problems. The 409 Conflict response is used to mean that the item sent conflicts with existing data; the body of the response contains the error message. Any other response is considered an error, and the browser will revert to simple form submission.
Mike
Bookmarks