home
/**
* Add an onchange event handler to the specified textfield object
* to validate the user's input and autocomplete it if necessary.
* The type argument is the Metaweb type, such as "/music/artist"
* for which autocompletion should be done.
*
* The optional message argument specifies a document element into
* which error messages (such as "invalid input" or "incomplete input"
* should be displayed) The optional constraints argument is an object
* that contains additional MQL properties that should be added to the
* query. This can be use to further constrain the autocompletion
* beyond simple type-based autocompletion.
*
* If the callback handler determines that the user's input is invalid or
* incomplete, it sets the cssClass property to "invalid" or "incomplete"
* (overwriting any other class values specified by that property).
* You can define these CSS classes to set background colors or otherwise
* highlight fields that require the user's attention.
*
* Validity and autocompletion is done using the ~= pattern matching
* operator to ask for results of the specified type that begin with
* the specified string. The query requests that results are sorted by
* name and that only the first two are returned. If no results are
* returned, this means that the user's input is invalid. If exactly
* one result is returned, then the user's input is unique and
* autocompletion is performed. If two results are returned, then the
* user's input is not unique, but may still be valid, if the input
* matches the first result (because the results are sorted), and that
* result is a prefix of the second. If two results are returned and
* the first result is not the same as the user's input, then the
* input is incomplete.
*
* This function sets the onchange and class attributes of the text
* field element and should not be used with HTML elements that set
* these attributes themselves. Also, this function alters the
* visibility and content of the optional message element.
*/
Metaweb.addValidationAndCompletion = function(textfield, type,
message, constraints)
{
// Ensure that the message element, if any, is hidden
if (message) message.style.visibility = "hidden";
// And add an event handler to the text field.
textfield.onchange = function() {
// Get the user's input and convert to lowercase.
// Metaweb does case-insensitive pattern matching.
var input = this.value.toLowerCase();
// This is the MQL query we use for autocompletion
var query = [{
type: type, // Find objects of this type
name: null, // We want to know object name
"name~=": "^" + input + "*", // ^ and * make this a prefix match
sort: "name", // Shortest completions first
limit: 2 // We only care about the first 2
}];
// Add any additional constraints to the query
if (constraints) for (c in constraints) query[0][c] = constraints[c];
// Now submit the query and pass the results to the nested function
Metaweb.read(query, function(results) {
// If there are no results, input is invalid
if (results.length == 0) {
// Set invalid class and display invalid message
textfield.className = "invalid";
if (message) {
message.innerHTML = "invalid input";
message.style.visibility = "visible";
}
}
// If there is one result or if the first result
// matches exactly, input is valid.
else if (results.length == 1 ||
results[0].name.toLowerCase() == input) {
// Autocomplete the value.
// Use capitalization Metaweb returns to us
textfield.value = results[0].name;
// Clear class and message
textfield.className = "";
if (message) {
message.innerHTML = "";
message.style.visibility = "hidden";
}
}
// If there is more than one result and no match
// then the user's input is incomplete
else {
// Set incomplete class and message
textfield.className = "incomplete";
if (message) {
message.innerHTML="incomplete input";
message.style.visibility = "visible";
}
}
});
}
}