In this article, I will demonstrate how to use YUI DataTable and DataSource to create a page that lets users search client records by client's first name, last name, and ID. If any client record is found, we display the search results in a table on the same page.
For DataSource, I use ScriptNodeDataSource. One of the major advantages of the ScriptNodeDataSource is that its data requests can be sent across domains by using JSONP (JSON Padding) instead of XHR. More discussions about JSONP can be found here.
First, let's define a ScriptNodeDataSource and response schema.
// Setup remote data source
var ds = new YAHOO.util.ScriptNodeDataSource(
'http://www.anotherdomain.com/search/');
// The response JSON will have a results array
// Each result object has userId, firstName, lastName, birthDate,
// address1, address2, address3, city, state, and zip properties.
ds.responseSchema = {
resultsList: "results",
fields: [ "userId", "firstName", "lastName", "birthDate",
"address1", "address2", "address3", "city", "state", "zip" ]
};
Define table columns. Use column formatters for column name, date, and address. Sort table rows by names.
//
// Column formatters
//
// Format column Name
var formatName = function(elCell, oRecord, oColumn, oData) {
// Concat the last name and first name
var strName = oRecord.getData("lastName") + ", "
+ oRecord.getData("firstName");
// Wrap name in a link that goes to client details page
var strUserId = oRecord.getData("userId");
elCell.innerHTML = '<a href="' + getResultUrl(strUserId)
+ '">' + strName + '</a>';
};
// Format column DOB
var formatDate = function(elCell, oRecord, oColumn, oData) {
if (YAHOO.lang.isString(oData))
{
if (Y.env.ua.ie > 0)
{
// IE has problem to parse date string "yyyy-mm-ddT00:00:00"
// Here, we fall back to manipulating the date string
elCell.innerHTML = oData.split("T")[0].replace(/-/g, "/");
}
else
{
var oDate = new Date(oData);
elCell.innerHTML = oDate.format("mm/dd/yyyy");
}
}
};
// Format column Address
var formatAddress = function(elCell, oRecord, oColumn, oData) {
var strAddr = oRecord.getData("address1") + " "
+ oRecord.getData("address2") + " "
+ oRecord.getData("address3");
strAddr = strAddr.trim() + ", " + oRecord.getData("city") + ", "
+ oRecord.getData("state") + " " + oRecord.getData("zip");
elCell.innerHTML = strAddr;
};
//
// Sorters
//
// Sort by name
var sortName = function(a, b, desc) {
var fnComp = YAHOO.util.Sort.compare;
var compState = fnComp(a.getData("lastName"),
b.getData("lastName"), desc);
if (compState == 0)
{
compState = fnComp(a.getData("firstName"),
b.getData("firstName"), desc);
}
return compState;
};
// Column definitions
var colDefs = [
{
key: "name", label: "Name",
resizeable: true, sortable: true,
formatter: formatName, // formatName column formatter
width: 120,
sortOptions: { sortFunction: sortName } // sortName sort function
},
{
key: "address", label: "Address",
resizeable: true, sortable: true,
formatter: formatAddress, // formatAddress column formatter
width: 250
},
{
key: "birthDate", label: "DOB",
resizeable: true, sortable: true,
formatter: formatDate // formatDate column formatter
},
{
key: "userId", label: "Client ID",
resizeable: true, sortable: true
}
];
Setup table configuration. When the table is created, the data table will send out an initial request to get data. We want to capture this initial request, and prevent the server side from starting any search work, because at this moment our user hasn't filled any search keywords in the text fields yet (First Name, Last Name, and Client ID text fields). The initial request is not triggered by our users. It has to be filtered out. To do this, we append "&init=true" parameter to the initial request's URL so the server side will know.
// Table configurations
var tableCfg = {
initialRequest: "&init=true",
sortedBy: {
key: "name", dir: "asc"
},
width: "100%",
height: "30em",
MSG_LOADING: "",
MSG_EMPTY: ""
};
The beef is here --- the search function which is responsible of gathering user inputs, validation, clearing previous search results in the table, constructing search queries, sending out query requests, displaying returned results, and handling errors.
// Field validation
var validate = function(params)
{
// Validation logics go here ...
return true;
};
// Search function.
// It will be invoked when users click the "Search" button
var fnSearch = function(e) {
// Suppress form submission
YAHOO.util.Event.stopEvent(e);
// Get search field values
var params = {
"firstName": document.getElementById("firstName").value,
"lastName": document.getElementById("lastName").value,
"userId": document.getElementById("userId").value
};
// Field validations
if (validate(params) == false)
{
return false;
}
// Callbacks for datasource.sendRequest
var callbacks = {
success: function(oRequest, oParsedResponse, oPayload) {
console.log("Retrieved search results");
// Enable the table
table.undisable();
// Flush and update the table content
table.onDataReturnInitializeTable.apply(table, arguments);
// Sort by name in ascending order
table.sortColumn(table.getColumn("name"),
YAHOO.widget.DataTable.CLASS_ASC);
// Update the count of search results
document.getElementById("results-count").innerHTML =
" - " + oParsedResponse.results.length + " result(s)";
},
failure: function() {
console.log("Failed to get search results");
// Failure handling code
},
scope: table
};
// Delete any existing rows, clear result count,
// and disable the table
table.deleteRows(0, table.getRecordSet().getLength());
document.getElementById("results-count").innerHTML = "";
table.disable();
// Construct search query
var strQuery = "";
for(var key in params)
{
strQuery += "&" + key + "=" + params[key].trim();
}
// Send out query request
ds.sendRequest(strQuery, callbacks);
console.log("Data source sent out request");
return false;
};
Hook up the search function with the button click event. And finally, create the table.
YAHOO.util.Event.addListener("search-btn", "click", fnSearch);
// Construct data table. Pass in column definitions, data source,
// and table configuration
var table = new YAHOO.widget.ScrollingDataTable("results-table",
colDefs, ds, tableCfg);
console.log("Constructed data table");

No comments:
Post a Comment