/**
 * 
 * Author : andrei.rafai
 * 
 * 
 * Usage example: $("#container").listSort({ keySelector: "h4", asc: false });
 * 
 * <div id="container">
 * <h4> a</h4>
 * <h4> c</h4>
 * <h4> b</h4>
 * <h4> d</h4>
 * </div>
 * 
 * the result will be <div id="container">
 * <h4> d</h4>
 * <h4> c</h4>
 * <h4> b</h4>
 * <h4> a</h4>
 * </div>
 */
(function($) {
	var defaults = {
		keySelector : "",
		dataKey : "",
		asc : true,
		before : function($container) {
			$container.next(":has(.pagination)").remove().end()
					  .prev(":has(.pagination)").remove();
		},
		after : function($container) {
		}
	};

	$.fn.listSort = function(userOptions) {
		var options = $.extend({}, defaults, userOptions);

		return this.each(function() {
			var $container = $(this);
			var itemList = [];
			var stringsPresent = false;

			$.each($container.children(), function() {
				// extract values to be sorted
				if (options.dataKey) {
					var keyValue = $(this).data(options.dataKey);
				} else {
					var keyValue = $(this).find(options.keySelector).html();
				}
				// force lower case sorting for non-number values
				if (isNaN(keyValue)) {
					keyValue = $.trim(keyValue).toLowerCase();
					stringsPresent = true;
				}
				// remove pagination related data
				this.className = this.className.replace(/\bpage.*?\b/g, '');
				// add entry
				itemList.push({
					key : keyValue,
					value : this
				});
			});

			// action before sorting (by default, pagination related markup is removed)
			options.before($container);

			// delete the original list in order to make room for the sorted list
			$container.empty();

			// sort extracted item list
			itemList.sort(function(a, b) {
				var key1 = (stringsPresent) ? "" + a.key : a.key;
				var key2 = (stringsPresent) ? "" + b.key : b.key;

				if (options.asc) {
					return (key1 > key2) ? 1 : -1;
				} else {
					return (key1 < key2) ? 1 : -1;
				}
			});

			// added sorted content to the provided container
			for ( var i in itemList) {
				var mapEntry = itemList[i];
				$(mapEntry.value).appendTo($container);
			}

			// action after sorting (by default, pagination logic is executed)
			options.after($container);
		});
	};
})(jQuery)

