Blog

The Haycroft Media Blog covers all aspects of website design and development from the web browsers being used through to the standards that govern the world wide web. As a website design and development company, it is imperative that we keep abreast of all the latest news and happenings in our field, and here we present the major stories along with tutorials, tips and other web-programming related items.

jQuery dataTables sorting, filtering and saved state

The Pears Property Group website involves pages of property listings that need to be sortable as well as filtered by area.

As jQuery is our javascript library of choice we opted for a jQuery based solution. We looked at various solutions, but the problem we had with most of them was that if the user sorted a table of data and then clicked on the ‘read more’ link for a particular property before clicking back to the data table, the data would revert back to its original state. After some fairly extensive research involving a fair few blind alleys, we opted for the dataTables plugin as it included an option to save the table state to a cookie.

Using the ‘Industrial properties to Buy‘ page as an example, you can see that the Area column can be filtered and the ‘Sort by area’ , ‘Size’ and ‘Price’ fields can be sorted ascending or descending. As previously mentioned, we also want to save the state of the table to a cookie.

We started by initialising the table as follows:

jQuery(document).ready( function () {
	var oTable = jQuery('#commercial_results').dataTable( {
	"aaSorting": [[ 1, "asc" ]],
/*sort by column 1 (Sort by Area) on page load, if no cookie defined */
	"bPaginate": false,
/* no pagination, all data to display in one continuous table */
	"bInfo": false,
	"bAutoWidth": false,
/* hide info and disable auto-width - active by default as part of the plugin */
	"bStateSave": true
/*save state to a cookie */
	"aoColumns": [
					{ "bSortable": false },
/*filter by area column won't be sortable
					null,
/*default settings for sort by area column
					{ "sType": "numeric" },
/*size column will contain numeric data
					{ "sType": "numeric" },
/*price column will contain numeric data
					{ "bSortable": false }
				]
} );

Filter by Area
As the client had a specific design for the page, we would have to set up our own filter. We would also need to pass unique area values to the filter. Firstly we ran a query to set-up a unique array of all areas assigned to our properties. We then set-up the table header using the array to define an area drop-down:

<thead>
	<tr>
		<th id="region">
			<select>
				<option value="" selected="selected">-- Filter by Area --</option>
				<option value="All">All</option>
			<?php
			foreach ( $unique_regions as $region ){
				echo '<option value="' . $region . '">' . $region . '</option>';
			}
			?>
			</select>
		</th>
		<th>Sort by area</th>
		<th>Size (m&sup2;)</th>
		<th>Price <?php echo $price;?></th>
		<th>More</th>
	</tr>
</thead>

A bit of additional code passes the selected value to the filter function:

jQuery('thead select').change( function() {
	select_val = jQuery(this).val();
	if (select_val == "All" || select_val == '') {
		oTable.fnFilter("");
		oTable.fnDraw();
	} else {
		oTable.fnFilter(select_val);
	}
	jQuery('thead select').val(select_val);
} );

Numeric Data
The Price and Area fields through up a few more issues as they needed to be sorted as numeric data, but some properties have negotiable prices, some properties have a range of plot sizes available, some numbers are four figures and all ‘to let’ prices needed have decimal points. All of these factors throw the default numerical sorting out of whack so a little customisation was required.

Firstly, it was decided to enter a value of 0 for both negotiable prices, and variable plot sizes. The dataTables ‘fnRowCallback’ function could then be used to display ‘Neg.’ or ‘Various’ respectively while retaining the sorting order. Secondly, values of four digits or more were to have no thousand separator added at data entry, but the same callback function would add them using a function from mredkj.com. Decimal places were added to all the property to let prices by a php function on retrieving the data from the database.

Here’s the full code:

function addCommas(nStr){
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}
jQuery(document).ready( function () {
	var oTable = jQuery('#commercial_results').dataTable( {
	"aaSorting": [[ 1, "asc" ]],
	"bPaginate": false,
	"bInfo": false,
	"bAutoWidth": false,
	"bStateSave": true,
	"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
		if ( aData[3] == "0" ){
			jQuery('td:eq(3)', nRow).html( 'Neg.' );
		} else {
			var no = addCommas( aData[3] );
			jQuery('td:eq(3)', nRow).html( no );
		}
		if ( aData[2] == "0" ){
			jQuery('td:eq(2)', nRow).html( 'Various' );
		} else {
			var no = addCommas( aData[2] );
			jQuery('td:eq(2)', nRow).html( no );
		}
		return nRow;
	},
	"aoColumns": [
					{ "bSortable": false },
					null,
					{ "sType": "numeric" },
					{ "sType": "numeric" },
					{ "bSortable": false }
				]
} );

In a final twist, the client decided that the state saving should only be temporary and that when the user navigated away from the page in use (other than viewing more info), the cookie should be destroyed. This was acheived by generating an array of all six cookies that could be created ( cookie_array() ) and on page load, passing the value of the cookie pertaining to the current page and setting the expiry of the other cookies to ’1′ (this equates to 1 sec past midnight on 1st Jan 1970). It is important to note that you include a path, or WordPress won’t allow you to amend the cookie:

foreach ( $cookies as $cookie ) {
	if ( $cookie != $current ) {
		setcookie( $cookie, '', 1, "/" );
	}
}
[ Back ]

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Facebook Comments