Example: Recordset Sort Plugin

The RecordsetSort plugin provides methods to allow for default and custom sorting on a Recordset instance.

State Population Land Area


The Sort plugin for Recordset allows a Recordset to have default and custom sorting functionality.

Using the Plugin

The RecordsetSort plugin can be "plugged in" to any Recordset instance using the plug method. Methods that exist on the plugin can be called using the sort namespace

YUI().use("recordset-base", "recordset-sort", function(Y) {
    
	//Add "recordset-sort" in the use statement.

	var data = [
		{a:3, b:2, c:1},
		{a:9, b:8, c:7},
		{a:1, b:2, c:3}
	],
	
	//Recordset is created with the objects from the data array
	myRecordset = new Y.Recordset({records: data});
	
	//Plugging in Sorting functionality
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	//You can now call sort methods on the myRecordset instance using the "sort" namespace.
	
	myRecordset.sort.sort();

});

Using the RecordsetSort Plugin

Default Sorting

If a custom sort function is not defined, RecordsetSort sorts using the default sorter as found in the Arraysort module's compare method. In the default sorter, two records are compared based on the key specified. If the values are equal, the IDs of the records are compared.

You can sort a Recordset using the default sort method by calling the sort method. Two arguments must be passed in: a string of the key to sort by, and a boolean representing if the sort order is descending or not.

YUI().use("recordset-base","recordset-sort", function(Y) {
    var data = [
		{a:3, b:2, c:1},
		{a:9, b:8, c:7},
		{a:1, b:2, c:3}
	],
	
	//Recordset is created with the objects from the data array
	myRecordset = new Y.Recordset({records: data});
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	//sorts the Recordset in ascending order using the value at 'a'
	myRecordset.sort.sort('a', false);
	
	//sorts the Recordset in descending order using the value at 'b'
	myRecordset.sort.sort('b', true);

});

Resorting

If the Recordset has been sorted at some point in time, the resort method can be called, which will sort the Recordset using the last-used options.

Optionally, the last used options to sort the Recordset can be retrieved through the lastSortProperties attribute.

YUI().use("recordst-base", "recordset-sort", function(Y) {
    var data = [
		{a:3, b:2, c:1},
		{a:9, b:8, c:7},
		{a:1, b:2, c:3}
	],
	
	//Recordset is created with the objects from the data array
	myRecordset = new Y.Recordset({records: data});
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	//sorts the Recordset in ascending order using the value at 'a'
	myRecordset.sort.sort('a', false);
	
	//Add a record so that the Recordset is no longer sorted
	myRecordset.add({a:10, b:60, c:0});
	
	//Resort the Recordset in ascending order using the value at 'a'
	myRecordset.sort.resort();
});

Reversing the Recordset

The order of the Recordset can be reversed by calling the reverse method. This method does not sort the Recordset.

YUI().use("recordset-base", "recordset-sort", function(Y) {
    var data = [
        {key:"a", label:"Column A"},
        {key:"b", label:"Column B"},
        {key:"c", label:"Column C"}
    ],
	
	myRecordset = new Y.Recordset({records:data});
	
	myRecordset.sort.reverse(); //now the first record in the Recordset will be {key:"c", label:"Column C"}
});

Flipping the Sort Order

As opposed to reverse, the flip method looks at the last-used sort options, and reapplies the sort in the opposite order (ie: descending if the Recordset was initially in ascending order). The Recordset does not have to be in a sorted state. This method does perform a sort.

YUI().use("recordset-base", "recordset-sort", function(Y) {
    var data = [
		{a:3, b:2, c:1},
		{a:9, b:8, c:7},
		{a:1, b:2, c:3}
	],
	
	//Recordset is created with the objects from the data array
	myRecordset = new Y.Recordset({records: data});
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	//sorts the Recordset in ascending order using the value at 'a'
	myRecordset.sort.sort('a', false);
	
	myRecordset.add({a:10, b:6, c:0});
	
	//sorts the Recordset in descending order using the value at 'a'
	myRecordset.sort.flip();
});

Providing a Custom Sort Function

A custom sort function can be provided to the sort plugin very easily. The sort method accepts a custom sort function as a third argument, and if it receives one, it will use it rather than the default sorter. The custom sort function should be written such that it compares two records, and returns one or the other, based on comparator operations.

YUI().use("recordset-base", "recordset-sort", function(Y) {
    var data = [
        {key:"a", label:"Column A"},
        {key:"b", label:"Column B"},
        {key:"c", label:"Column C"}
    ],
	
	myRecordset = new Y.Recordset({records:data});
	
	
	//Define a custom sort function, which first compares values in the specified key, and if its a tie,
	//compares value in key 'b'. If that's also a tie, it looks at the IDs.
	 customsort = function(recA, recB, field, desc) {
        var first_sorted = compare(recA.getValue(field), recB.getValue(field), desc);
        if(first_sorted === 0) {
            var second_sorted = compare(recA.getValue('b'), recB.getValue('b'), desc);
			if (second_sorted === 0) {
				return compare(recA.getValue("id"), recB.get("id"), desc);
			}
			else {
				return second_sorted;
			}
        }
        else {
            return first_sorted;
        }
    };

	//Sort the Recordset using the custom sort function.
	myRecordset.sort.sort('a',false, customsort);
});

Helper Attributes and Events

Sorting is usually an expensive operation, so the RecordsetSort plug-in has some attributes to allow you to decide whether you need to sort or not.

Is the Recordset already sorted?

The isSorted attribute is a boolean that designates if the Recordset is in a sorted state. Under the hood, isSorted will change to false if records have been added (or updated), but will not change if records have been removed.

YUI().use("recordset-base", "recordset-sort", function(Y) {
    var data = [
        {key:"a", label:"Column A"},
        {key:"b", label:"Column B"},
        {key:"c", label:"Column C"}
    ],
	
	myRecordset = new Y.Recordset({records:data});
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	myRecordset.sort.get('isSorted'); //returns false
	
	myRecordset.sort.sort('a', true);
	myRecordset.sort.get('isSorted'); //returns true
	
	myRecordset.remove(1);
	myRecordset.sort.get('isSorted'); //returns true
	
	myRecordset.add({a:10, b:50, c:60});
	myRecordset.sort.get('isSorted'); //returns false
	
	
});

By setting up hooks on the isSorted attribute change events, you can better determine whether or not to perform a sort operation.

Find last-used sort properties

The lastSortProperties attribute stores an object literal of the last properties used to sort the Recordset.

YUI().use("recordset-base", "recordset-sort", function(Y) {
    var data = [
        {key:"a", label:"Column A"},
        {key:"b", label:"Column B"},
        {key:"c", label:"Column C"}
    ],
	
	myRecordset = new Y.Recordset({records:data});
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	myRecordset.sort.sort('a', true);
	var sortProperties = myRecordset.sort.get('lastSortProperties'); 
	
	/* 
	
	sortProperties is an object literal containing: 
	{
		field: 'a',
		desc: 'true',
		sorter: defaultSorter
	}
	
	*/
	
});
'sort' Event

The RecordsetSort plugin fires the 'sort' event whenever it sorts a Recordset. Hooking onto this event using the on method triggers code to be run before the sort occurs. On the other hand, using the 'after' method triggers your code to be run after the sort.

The object returned with the event has the same fields as the lastSortProperties object.

YUI().use("recordset-base", "recordset-sort", function(Y) {
    var data = [
        {key:"a", label:"Column A"},
        {key:"b", label:"Column B"},
        {key:"c", label:"Column C"}
    ],
	
	myRecordset = new Y.Recordset({records:data});
	myRecordset.plug(Y.Plugin.RecordsetSort);
	
	myRecordset.sort.on('sort', function(e) {
		Y.log('this Recordset is about to be sorted');
	});
	
	myRecordset.sort.sort('a', true);
	
});