﻿/*
* jQuery Diff
*/
(function ($)
{
	var _priv = {
		cyclicCheck: null,
		diff: function (obj1, obj2)
		{
			if (typeof obj1 === "undefined") obj1 = {};
			if (typeof obj2 === "undefined") obj2 = {};
			var val1, val2, mod = {},
				add = {},
				del = {},
				ret;
			jQuery.each(obj2, function (key, val2)
			{
				val1 = obj1[key];
				bDiff = false;
				if (typeof val1 === "undefined") add[key] = val2;
				else if (typeof val1 != typeof val2) mod[key] = val2;
				else if (val1 !== val2) if (typeof val2 === "object")
				{
					if (_priv.cyclicCheck.indexOf(val2) >= 0) return false;
					ret = _priv.diff(val1, val2);
					if (!$.isEmptyObject(ret.mod)) mod[key] = $.extend(true, {}, ret.mod);
					if (!$.isEmptyObject(ret.add)) add[key] = $.extend(true, {}, ret.add);
					if (!$.isEmptyObject(ret.del)) del[key] = $.extend(true, {}, ret.del);
					_priv.cyclicCheck.push(val2)
				} else mod[key] = val2
			});
			jQuery.each(obj1, function (key, val1)
			{
				if (typeof obj2[key] === "undefined") del[key] = true
			});
			return {
				mod: mod,
				add: add,
				del: del
			}
		}
	};
	jQuery.diff = function (obj1, obj2)
	{
		_priv.cyclicCheck = [];
		return _priv.diff(obj1, obj2)
	}
})(jQuery);
/*
* JavaScript Debug - v0.4 - 6/22/2010
* http://benalman.com/projects/javascript-debug-console-log/
* 
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
* 
* With lots of help from Paul Irish!
* http://paulirish.com/
*/
window.debug = (function ()
{
	var i = this,
		b = Array.prototype.slice,
		d = i.console,
		h = {},
		f, g, m = 9,
		c = ["error", "warn", "info", "debug", "log"],
		l = "assert clear count dir dirxml exception group groupCollapsed groupEnd profile profileEnd table time timeEnd trace".split(" "),
		j = l.length,
		a = [];
	while (--j >= 0)
	{
		(function (n)
		{
			h[n] = function ()
			{
				m !== 0 && d && d[n] && d[n].apply(d, arguments)
			}
		})(l[j])
	}
	j = c.length;
	while (--j >= 0)
	{
		(function (n, o)
		{
			h[o] = function ()
			{
				var q = b.call(arguments),
					p = [o].concat(q);
				a.push(p);
				e(p);
				if (!d || !k(n))
				{
					return
				}
				d.firebug ? d[o].apply(i, q) : d[o] ? d[o](q) : d.log(q)
			}
		})(j, c[j])
	}
	function e(n)
	{
		if (f && (g || !d || !d.log))
		{
			f.apply(i, n)
		}
	}
	h.setLevel = function (n)
	{
		m = typeof n === "number" ? n : 9
	};
	function k(n)
	{
		return m > 0 ? m > n : c.length + m <= n
	}
	h.setCallback = function ()
	{
		var o = b.call(arguments),
			n = a.length,
			p = n;
		f = o.shift() || null;
		g = typeof o[0] === "boolean" ? o.shift() : false;
		p -= typeof o[0] === "number" ? o.shift() : n;
		while (p < n)
		{
			e(a[p++])
		}
	};
	return h
})();
/*
AUTHOR James Padolsey (http://james.padolsey.com)
VERSION 1.02.1
UPDATED 07-14-2009
CONTRIBUTORS
David Waller
*/
var prettyPrint = (function ()
{
	/* These "util" functions are not part of the core
	functionality but are  all necessary - mostly DOM helpers */
	var util = {
		el: function (type, attrs)
		{ /* Create new element */
			var el = document.createElement(type),
				attr; /*Copy to single object */
			attrs = util.merge({}, attrs); /* Add attributes to el */
			if (attrs && attrs.style)
			{
				var styles = attrs.style;
				util.applyCSS(el, attrs.style);
				delete attrs.style;
			}
			for (attr in attrs)
			{
				if (attrs.hasOwnProperty(attr))
				{
					el[attr] = attrs[attr];
				}
			}
			return el;
		},
		applyCSS: function (el, styles)
		{ /* Applies CSS to a single element */
			for (var prop in styles)
			{
				if (styles.hasOwnProperty(prop))
				{
					try
					{ /* Yes, IE6 SUCKS! */
						el.style[prop] = styles[prop];
					} catch (e) { }
				}
			}
		},
		txt: function (t)
		{ /* Create text node */
			return document.createTextNode(t);
		},
		row: function (cells, type, cellType)
		{ /* Creates new <tr> */
			cellType = cellType || 'td'; /* colSpan is calculated by length of null items in array */
			var colSpan = util.count(cells, null) + 1,
				tr = util.el('tr'),
				td, attrs = {
					style: util.getStyles(cellType, type),
					colSpan: colSpan,
					onmouseover: function ()
					{
						var tds = this.parentNode.childNodes;
						util.forEach(tds, function (cell)
						{
							if (cell.nodeName.toLowerCase() !== 'td')
							{
								return;
							}
							util.applyCSS(cell, util.getStyles('td_hover', type));
						});
					},
					onmouseout: function ()
					{
						var tds = this.parentNode.childNodes;
						util.forEach(tds, function (cell)
						{
							if (cell.nodeName.toLowerCase() !== 'td')
							{
								return;
							}
							util.applyCSS(cell, util.getStyles('td', type));
						});
					}
				};
			util.forEach(cells, function (cell)
			{
				if (cell === null)
				{
					return;
				} /* Default cell type is <td> */
				td = util.el(cellType, attrs);
				if (cell.nodeType)
				{ /* IsDomElement */
					td.appendChild(cell);
				} else
				{ /* IsString */
					td.innerHTML = util.shorten(cell.toString());
				}
				tr.appendChild(td);
			});
			return tr;
		},
		hRow: function (cells, type)
		{ /* Return new <th> */
			return util.row(cells, type, 'th');
		},
		table: function (headings, type)
		{
			headings = headings || []; /* Creates new table: */
			var attrs = {
				thead: {
					style: util.getStyles('thead', type)
				},
				tbody: {
					style: util.getStyles('tbody', type)
				},
				table: {
					style: util.getStyles('table', type)
				}
			},
				tbl = util.el('table', attrs.table),
				thead = util.el('thead', attrs.thead),
				tbody = util.el('tbody', attrs.tbody);
			if (headings.length)
			{
				tbl.appendChild(thead);
				thead.appendChild(util.hRow(headings, type));
			}
			tbl.appendChild(tbody);
			return {
				/* Facade for dealing with table/tbody
				Actual table node is this.node: */
				node: tbl,
				tbody: tbody,
				thead: thead,
				appendChild: function (node)
				{
					this.tbody.appendChild(node);
				},
				addRow: function (cells, _type, cellType)
				{
					this.appendChild(util.row.call(util, cells, (_type || type), cellType));
					return this;
				}
			};
		},
		shorten: function (str)
		{
			var max = 40;
			str = str.replace(/^\s\s*|\s\s*$|\n/g, '');
			return str.length > max ? (str.substring(0, max - 1) + '...') : str;
		},
		htmlentities: function (str)
		{
			return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
		},
		merge: function (target, source)
		{
			/* Merges two (or more) objects,
			giving the last one precedence */
			if (typeof target !== 'object')
			{
				target = {};
			}
			for (var property in source)
			{
				if (source.hasOwnProperty(property))
				{
					var sourceProperty = source[property];
					if (typeof sourceProperty === 'object')
					{
						target[property] = util.merge(target[property], sourceProperty);
						continue;
					}
					target[property] = sourceProperty;
				}
			}
			for (var a = 2, l = arguments.length; a < l; a++)
			{
				util.merge(target, arguments[a]);
			}
			return target;
		},
		count: function (arr, item)
		{
			var count = 0;
			for (var i = 0, l = arr.length; i < l; i++)
			{
				if (arr[i] === item)
				{
					count++;
				}
			}
			return count;
		},
		thead: function (tbl)
		{
			return tbl.getElementsByTagName('thead')[0];
		},
		forEach: function (arr, fn)
		{ /* Helper: iteration */
			var len = arr.length,
				index = -1;
			while (len > ++index)
			{
				if (fn(arr[index], index, arr) === false)
				{
					break;
				}
			}
			return true;
		},
		type: function (v)
		{
			try
			{
				/* Returns type, e.g. "string", "number", "array" etc.
				Note, this is only used for precise typing. */
				if (v === null)
				{
					return 'null';
				}
				if (v === undefined)
				{
					return 'undefined';
				}
				var oType = Object.prototype.toString.call(v).match(/\s(.+?)\]/)[1].toLowerCase();
				if (v.nodeType)
				{
					if (v.nodeType === 1)
					{
						return 'domelement';
					}
					return 'domnode';
				}
				if (/^(string|number|array|regexp|function|date|boolean)$/.test(oType))
				{
					return oType;
				}
				if (typeof v === 'object')
				{
					return v.jquery && typeof v.jquery === 'string' ? 'jquery' : 'object';
				}
				if (v === window || v === document)
				{
					return 'object';
				}
				return 'default';
			} catch (e)
			{
				return 'default';
			}
		},
		within: function (ref)
		{
			/* Check existence of a val within an object
			RETURNS KEY */
			return {
				is: function (o)
				{
					for (var i in ref)
					{
						if (ref[i] === o)
						{
							return i;
						}
					}
					return '';
				}
			};
		},
		common: {
			circRef: function (obj, key, settings)
			{
				return util.expander('[POINTS BACK TO <strong>' + (key) + '</strong>]', 'Click to show this item anyway', function ()
				{
					this.parentNode.appendChild(prettyPrintThis(obj, {
						maxDepth: 1
					}));
				});
			},
			depthReached: function (obj, settings)
			{
				return util.expander('[DEPTH REACHED]', 'Click to show this item anyway', function ()
				{
					try
					{
						this.parentNode.appendChild(prettyPrintThis(obj, {
							maxDepth: 1
						}));
					} catch (e)
					{
						this.parentNode.appendChild(
						util.table(['ERROR OCCURED DURING OBJECT RETRIEVAL'], 'error').addRow([e.message]).node);
					}
				});
			}
		},
		getStyles: function (el, type)
		{
			type = prettyPrintThis.settings.styles[type] || {};
			return util.merge({}, prettyPrintThis.settings.styles['default'][el], type[el]);
		},
		expander: function (text, title, clickFn)
		{
			return util.el('a', {
				innerHTML: util.shorten(text) + ' <b style="visibility:hidden;">[+]</b>',
				title: title,
				onmouseover: function ()
				{
					this.getElementsByTagName('b')[0].style.visibility = 'visible';
				},
				onmouseout: function ()
				{
					this.getElementsByTagName('b')[0].style.visibility = 'hidden';
				},
				onclick: function ()
				{
					this.style.display = 'none';
					clickFn.call(this);
					return false;
				},
				style: {
					cursor: 'pointer'
				}
			});
		},
		stringify: function (obj)
		{
			/* Bit of an ugly duckling!
			- This fn returns an ATTEMPT at converting an object/array/anyType
			into a string, kinda like a JSON-deParser
			- This is used for when |settings.expanded === false| */
			var type = util.type(obj),
				str, first = true;
			if (type === 'array')
			{
				str = '[';
				util.forEach(obj, function (item, i)
				{
					str += (i === 0 ? '' : ', ') + util.stringify(item);
				});
				return str + ']';
			}
			if (typeof obj === 'object')
			{
				str = '{';
				for (var i in obj)
				{
					if (obj.hasOwnProperty(i))
					{
						str += (first ? '' : ', ') + i + ':' + util.stringify(obj[i]);
						first = false;
					}
				}
				return str + '}';
			}
			if (type === 'regexp')
			{
				return '/' + obj.source + '/';
			}
			if (type === 'string')
			{
				return '"' + obj.replace(/"/g, '\\"') + '"';
			}
			return obj.toString();
		},
		headerGradient: (function ()
		{
			var canvas = document.createElement('canvas');
			if (!canvas.getContext)
			{
				return '';
			}
			var cx = canvas.getContext('2d');
			canvas.height = 30;
			canvas.width = 1;
			var linearGrad = cx.createLinearGradient(0, 0, 0, 30);
			linearGrad.addColorStop(0, 'rgba(0,0,0,0)');
			linearGrad.addColorStop(1, 'rgba(0,0,0,0.25)');
			cx.fillStyle = linearGrad;
			cx.fillRect(0, 0, 1, 30);
			var dataURL = canvas.toDataURL && canvas.toDataURL();
			return 'url(' + (dataURL || '') + ')';
		})()
	};
	// Main..
	var prettyPrintThis = function (obj, options)
	{
		/*
		*      obj :: Object to be printed                    
		*  options :: Options (merged with config)
		*/
		options = options || {};
		var settings = util.merge({}, prettyPrintThis.config, options),
			container = util.el('div'),
			config = prettyPrintThis.config,
			currentDepth = 0,
			stack = {},
			hasRunOnce = false;
		/* Expose per-call settings.
		Note: "config" is overwritten (where necessary) by options/"settings"
		So, if you need to access/change *DEFAULT* settings then go via ".config" */
		prettyPrintThis.settings = settings;
		var typeDealer = {
			string: function (item)
			{
				return util.txt('"' + util.shorten(item.replace(/"/g, '\\"')) + '"');
			},
			number: function (item)
			{
				return util.txt(item);
			},
			regexp: function (item)
			{
				var miniTable = util.table(['RegExp', null], 'regexp');
				var flags = util.table();
				var span = util.expander('/' + item.source + '/', 'Click to show more', function ()
				{
					this.parentNode.appendChild(miniTable.node);
				});
				flags.addRow(['g', item.global]).addRow(['i', item.ignoreCase]).addRow(['m', item.multiline]);
				miniTable.addRow(['source', '/' + item.source + '/']).addRow(['flags', flags.node]).addRow(['lastIndex', item.lastIndex]);
				return settings.expanded ? miniTable.node : span;
			},
			domelement: function (element, depth)
			{
				var miniTable = util.table(['DOMElement', null], 'domelement'),
					props = ['id', 'className', 'innerHTML', 'src', 'href'],
					elname = element.nodeName || '';
				miniTable.addRow(['tag', '&lt;' + elname.toLowerCase() + '&gt;']);
				util.forEach(props, function (prop)
				{
					if (element[prop])
					{
						miniTable.addRow([prop, util.htmlentities(element[prop])]);
					}
				});
				return settings.expanded ? miniTable.node : util.expander('DOMElement (' + elname.toLowerCase() + ')', 'Click to show more', function ()
				{
					this.parentNode.appendChild(miniTable.node);
				});
			},
			domnode: function (node)
			{ /* Deals with all DOMNodes that aren't elements (nodeType !== 1) */
				var miniTable = util.table(['DOMNode', null], 'domelement'),
					data = util.htmlentities((node.data || 'UNDEFINED').replace(/\n/g, '\\n'));
				miniTable.addRow(['nodeType', node.nodeType + ' (' + node.nodeName + ')']).addRow(['data', data]);
				return settings.expanded ? miniTable.node : util.expander('DOMNode', 'Click to show more', function ()
				{
					this.parentNode.appendChild(miniTable.node);
				});
			},
			jquery: function (obj, depth, key)
			{
				return typeDealer['array'](obj, depth, key, true);
			},
			object: function (obj, depth, key)
			{ /* Checking depth + circular refs */
				/* Note, check for circular refs before depth; just makes more sense */
				var stackKey = util.within(stack).is(obj);
				if (stackKey)
				{
					return util.common.circRef(obj, stackKey, settings);
				}
				stack[key || 'TOP'] = obj;
				if (depth === settings.maxDepth)
				{
					return util.common.depthReached(obj, settings);
				}
				var table = util.table(['Object', null], 'object'),
					isEmpty = true;
				for (var i in obj)
				{
					if (!obj.hasOwnProperty || obj.hasOwnProperty(i))
					{
						var item = obj[i],
							type = util.type(item);
						isEmpty = false;
						try
						{
							table.addRow([i, typeDealer[type](item, depth + 1, i)], type);
						} catch (e)
						{ /* Security errors are thrown on certain Window/DOM properties */
							if (window.console && window.console.log)
							{
								console.log(e.message);
							}
						}
					}
				}
				if (isEmpty)
				{
					table.addRow(['<small>[empty]</small>']);
				} else
				{
					table.thead.appendChild(
					util.hRow(['key', 'value'], 'colHeader'));
				}
				var ret = (settings.expanded || hasRunOnce) ? table.node : util.expander(
				util.stringify(obj), 'Click to show more', function ()
				{
					this.parentNode.appendChild(table.node);
				});
				hasRunOnce = true;
				return ret;
			},
			array: function (arr, depth, key, jquery)
			{ /* Checking depth + circular refs */
				/* Note, check for circular refs before depth; just makes more sense */
				var stackKey = util.within(stack).is(arr);
				if (stackKey)
				{
					return util.common.circRef(arr, stackKey);
				}
				stack[key || 'TOP'] = arr;
				if (depth === settings.maxDepth)
				{
					return util.common.depthReached(arr);
				} /* Accepts a table and modifies it */
				var me = jquery ? 'jQuery' : 'Array',
					table = util.table([me + '(' + arr.length + ')', null], jquery ? 'jquery' : me.toLowerCase()),
					isEmpty = true;
				if (jquery)
				{
					table.addRow(['selector', arr.selector]);
				}
				util.forEach(arr, function (item, i)
				{
					isEmpty = false;
					table.addRow([i, typeDealer[util.type(item)](item, depth + 1, i)]);
				});
				if (!jquery)
				{
					if (isEmpty)
					{
						table.addRow(['<small>[empty]</small>']);
					} else
					{
						table.thead.appendChild(util.hRow(['index', 'value'], 'colHeader'));
					}
				}
				return settings.expanded ? table.node : util.expander(
				util.stringify(arr), 'Click to show more', function ()
				{
					this.parentNode.appendChild(table.node);
				});
			},
			'function': function (fn, depth, key)
			{ /* Checking JUST circular refs */
				var stackKey = util.within(stack).is(fn);
				if (stackKey)
				{
					return util.common.circRef(fn, stackKey);
				}
				stack[key || 'TOP'] = fn;
				var miniTable = util.table(['Function', null], 'function'),
					argsTable = util.table(['Arguments']),
					args = fn.toString().match(/\((.+?)\)/),
					body = fn.toString().match(/\(.*?\)\s+?\{?([\S\s]+)/)[1].replace(/\}?$/, '');
				miniTable.addRow(['arguments', args ? args[1].replace(/[^\w_,\s]/g, '') : '<small>[none/native]</small>']).addRow(['body', body]);
				return settings.expanded ? miniTable.node : util.expander('function(){...}', 'Click to see more about this function.', function ()
				{
					this.parentNode.appendChild(miniTable.node);
				});
			},
			'date': function (date)
			{
				var miniTable = util.table(['Date', null], 'date'),
					sDate = date.toString().split(/\s/); /* TODO: Make this work well in IE! */
				miniTable.addRow(['Time', sDate[4]]).addRow(['Date', sDate.slice(0, 4).join('-')]);
				return settings.expanded ? miniTable.node : util.expander('Date (timestamp): ' + (+date), 'Click to see a little more info about this date', function ()
				{
					this.parentNode.appendChild(miniTable.node);
				});
			},
			'boolean': function (bool)
			{
				return util.txt(bool.toString().toUpperCase());
			},
			'undefined': function ()
			{
				return util.txt('UNDEFINED');
			},
			'null': function ()
			{
				return util.txt('NULL');
			},
			'default': function ()
			{ /* When a type cannot be found */
				return util.txt('prettyPrint: TypeNotFound Error');
			}
		};
		container.appendChild(typeDealer[(settings.forceObject) ? 'object' : util.type(obj)](obj, currentDepth));
		return container;
	}; /* Configuration */
	/* All items can be overwridden by passing an
	"options" object when calling prettyPrint */
	prettyPrintThis.config = { /* Try setting this to false to save space */
		expanded: true,
		forceObject: false,
		maxDepth: 1,
		styles: {
			array: {
				th: {
					backgroundColor: '#6DBD2A',
					color: 'white'
				}
			},
			'function': {
				th: {
					backgroundColor: '#D82525'
				}
			},
			regexp: {
				th: {
					backgroundColor: '#E2F3FB',
					color: '#000'
				}
			},
			object: {
				th: {
					backgroundColor: '#1F96CF'
				}
			},
			jquery: {
				th: {
					backgroundColor: '#FBF315'
				}
			},
			error: {
				th: {
					backgroundColor: 'red',
					color: 'yellow'
				}
			},
			domelement: {
				th: {
					backgroundColor: '#F3801E'
				}
			},
			date: {
				th: {
					backgroundColor: '#A725D8'
				}
			},
			colHeader: {
				th: {
					backgroundColor: '#EEE',
					color: '#000',
					textTransform: 'uppercase'
				}
			},
			'default': {
				table: {
					borderCollapse: 'collapse',
					width: '100%'
				},
				td: {
					padding: '5px',
					fontSize: '12px',
					backgroundColor: '#FFF',
					color: '#222',
					border: '1px solid #000',
					verticalAlign: 'top',
					fontFamily: '"Consolas","Lucida Console",Courier,mono',
					whiteSpace: 'nowrap'
				},
				td_hover: {
				/* Styles defined here will apply to all tr:hover > td,
				- Be aware that "inheritable" properties (e.g. fontWeight) WILL BE INHERITED */
			},
			th: {
				padding: '5px',
				fontSize: '12px',
				backgroundColor: '#222',
				color: '#EEE',
				textAlign: 'left',
				border: '1px solid #000',
				verticalAlign: 'top',
				fontFamily: '"Consolas","Lucida Console",Courier,mono',
				backgroundImage: util.headerGradient,
				backgroundRepeat: 'repeat-x'
			}
		}
	}
};
return prettyPrintThis;


})();




/*




Quicksand 1.2.2




Reorder and filter items with a nice shuffling animation.




Copyright (c) 2010 Jacek Galanciak (razorjack.net) and agilope.com



Big thanks for Piotr Petrus (riddle.pl) for deep code review and wonderful docs & demos.




Dual licensed under the MIT and GPL version 2 licenses.



http://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt



http://github.com/jquery/jquery/blob/master/GPL-LICENSE.txt




Project site: http://razorjack.net/quicksand



Github site: http://github.com/razorjack/quicksand




*/


(function ($)
{


	$.fn.quicksand = function (collection, customOptions)
	{

		var options = {


			duration: 750,


			easing: 'swing',


			attribute: 'data-id',


			// attribute to recognize same items within source and dest


			adjustHeight: 'auto',


			// 'dynamic' animates height during shuffling (slow), 'auto' adjusts it before or after the animation, false leaves height constant


			useScaling: true,


			// disable it if you're not using scaling effect or want to improve performance


			enhancement: function (c) { },


			// Visual enhacement (eg. font replacement) function for cloned elements


			selector: '> *',


			dx: 0,


			dy: 0


		};


		$.extend(options, customOptions);


		if ($.browser.msie || (typeof ($.fn.scale) == 'undefined'))
		{


			// Got IE and want scaling effect? Kiss my ass.


			options.useScaling = false;


		}


		var callbackFunction;


		if (typeof (arguments[1]) == 'function')
		{


			var callbackFunction = arguments[1];


		} else if (typeof (arguments[2] == 'function'))
		{


			var callbackFunction = arguments[2];


		}


		return this.each(function (i)
		{


			var val;


			var animationQueue = []; // used to store all the animation params before starting the animation; solves initial animation slowdowns


			var $collection = $(collection).clone(); // destination (target) collection


			var $sourceParent = $(this); // source, the visible container of source collection


			var sourceHeight = $(this).css('height'); // used to keep height and document flow during the animation


			var destHeight;


			var adjustHeightOnCallback = false;


			var offset = $($sourceParent).offset(); // offset of visible container, used in animation calculations


			var offsets = []; // coordinates of every source collection item            


			var $source = $(this).find(options.selector); // source collection items


			// Replace the collection and quit if IE6


			if ($.browser.msie && $.browser.version.substr(0, 1) < 7)
			{


				$sourceParent.html('').append($collection);


				return;


			}


			// Gets called when any animation is finished


			var postCallbackPerformed = 0; // prevents the function from being called more than one time


			var postCallback = function ()
			{


				if (!postCallbackPerformed)
				{


					postCallbackPerformed = 1;


					// hack: 


					// used to be: $sourceParent.html($dest.html()); // put target HTML into visible source container


					// but new webkit builds cause flickering when replacing the collections


					$toDelete = $sourceParent.find('> *');


					$sourceParent.prepend($dest.find('> *'));


					$toDelete.remove();


					if (adjustHeightOnCallback)
					{


						$sourceParent.css('height', destHeight);


					}


					options.enhancement($sourceParent); // Perform custom visual enhancements on a newly replaced collection


					if (typeof callbackFunction == 'function')
					{


						callbackFunction.call(this);


					}


				}


			};


			// Position: relative situations


			var $correctionParent = $sourceParent.offsetParent();


			var correctionOffset = $correctionParent.offset();


			if ($correctionParent.css('position') == 'relative')
			{


				if ($correctionParent.get(0).nodeName.toLowerCase() == 'body') { } else
				{


					correctionOffset.top += (parseFloat($correctionParent.css('border-top-width')) || 0);


					correctionOffset.left += (parseFloat($correctionParent.css('border-left-width')) || 0);


				}


			} else
			{


				correctionOffset.top -= (parseFloat($correctionParent.css('border-top-width')) || 0);


				correctionOffset.left -= (parseFloat($correctionParent.css('border-left-width')) || 0);


				correctionOffset.top -= (parseFloat($correctionParent.css('margin-top')) || 0);


				correctionOffset.left -= (parseFloat($correctionParent.css('margin-left')) || 0);


			}


			// perform custom corrections from options (use when Quicksand fails to detect proper correction)


			if (isNaN(correctionOffset.left))
			{


				correctionOffset.left = 0;


			}


			if (isNaN(correctionOffset.top))
			{


				correctionOffset.top = 0;


			}


			correctionOffset.left -= options.dx;


			correctionOffset.top -= options.dy;


			// keeps nodes after source container, holding their position


			$sourceParent.css('height', $(this).height());


			// get positions of source collections


			$source.each(function (i)
			{


				offsets[i] = $(this).offset();


			});


			// stops previous animations on source container


			$(this).stop();


			var dx = 0;


			var dy = 0;


			$source.each(function (i)
			{


				$(this).stop(); // stop animation of collection items


				var rawObj = $(this).get(0);


				if (rawObj.style.position == 'absolute')
				{


					dx = -options.dx;


					dy = -options.dy;


				} else
				{


					dx = options.dx;


					dy = options.dy;


				}


				rawObj.style.position = 'absolute';


				rawObj.style.margin = '0';


				rawObj.style.top = (offsets[i].top - parseFloat(rawObj.style.marginTop) - correctionOffset.top + dy) + 'px';


				rawObj.style.left = (offsets[i].left - parseFloat(rawObj.style.marginLeft) - correctionOffset.left + dx) + 'px';


			});


			// create temporary container with destination collection


			var $dest = $($sourceParent).clone();


			var rawDest = $dest.get(0);


			rawDest.innerHTML = '';


			rawDest.setAttribute('id', '');


			rawDest.style.height = 'auto';


			rawDest.style.width = $sourceParent.width() + 'px';


			$dest.append($collection);


			// insert node into HTML


			// Note that the node is under visible source container in the exactly same position


			// The browser render all the items without showing them (opacity: 0.0)


			// No offset calculations are needed, the browser just extracts position from underlayered destination items


			// and sets animation to destination positions.


			$dest.insertBefore($sourceParent);


			$dest.css('opacity', 0.0);


			rawDest.style.zIndex = -1;


			rawDest.style.margin = '0';


			rawDest.style.position = 'absolute';


			rawDest.style.top = offset.top - correctionOffset.top + 'px';


			rawDest.style.left = offset.left - correctionOffset.left + 'px';


			if (options.adjustHeight === 'dynamic')
			{


				// If destination container has different height than source container


				// the height can be animated, adjusting it to destination height


				$sourceParent.animate({


					height: $dest.height()


				}, options.duration, options.easing);


			} else if (options.adjustHeight === 'auto')
			{


				destHeight = $dest.height();


				if (parseFloat(sourceHeight) < parseFloat(destHeight))
				{


					// Adjust the height now so that the items don't move out of the container


					$sourceParent.css('height', destHeight);


				} else
				{


					//  Adjust later, on callback


					adjustHeightOnCallback = true;


				}


			}


			// Now it's time to do shuffling animation


			// First of all, we need to identify same elements within source and destination collections    


			$source.each(function (i)
			{


				var destElement = [];


				if (typeof (options.attribute) == 'function')
				{


					val = options.attribute($(this));


					$collection.each(function ()
					{


						if (options.attribute(this) == val)
						{


							destElement = $(this);


							return false;


						}


					});


				} else
				{


					destElement = $collection.filter('[' + options.attribute + '=' + $(this).attr(options.attribute) + ']');


				}


				if (destElement.length)
				{


					// The item is both in source and destination collections


					// It it's under different position, let's move it


					if (!options.useScaling)
					{


						animationQueue.push({


							element: $(this),


							animation: {


								top: destElement.offset().top - correctionOffset.top,


								left: destElement.offset().left - correctionOffset.left,


								opacity: 1.0


							}


						});


					} else
					{


						animationQueue.push({


							element: $(this),


							animation: {


								top: destElement.offset().top - correctionOffset.top,


								left: destElement.offset().left - correctionOffset.left,


								opacity: 1.0,


								scale: '1.0'


							}


						});


					}


				} else
				{


					// The item from source collection is not present in destination collections


					// Let's remove it


					if (!options.useScaling)
					{


						animationQueue.push({


							element: $(this),


							animation: {


								opacity: '0.0'


							}


						});


					} else
					{


						animationQueue.push({


							element: $(this),


							animation: {


								opacity: '0.0',


								scale: '0.0'


							}


						});


					}


				}


			});


			$collection.each(function (i)
			{


				// Grab all items from target collection not present in visible source collection


				var sourceElement = [];


				var destElement = [];


				if (typeof (options.attribute) == 'function')
				{


					val = options.attribute($(this));


					$source.each(function ()
					{


						if (options.attribute(this) == val)
						{


							sourceElement = $(this);


							return false;


						}


					});


					$collection.each(function ()
					{


						if (options.attribute(this) == val)
						{


							destElement = $(this);


							return false;


						}


					});


				} else
				{


					sourceElement = $source.filter('[' + options.attribute + '=' + $(this).attr(options.attribute) + ']');


					destElement = $collection.filter('[' + options.attribute + '=' + $(this).attr(options.attribute) + ']');


				}


				var animationOptions;


				if (sourceElement.length === 0)
				{


					// No such element in source collection...


					if (!options.useScaling)
					{


						animationOptions = {


							opacity: '1.0'


						};


					} else
					{


						animationOptions = {


							opacity: '1.0',


							scale: '1.0'


						};


					}


					// Let's create it


					d = destElement.clone();


					var rawDestElement = d.get(0);


					rawDestElement.style.position = 'absolute';


					rawDestElement.style.margin = '0';


					rawDestElement.style.top = destElement.offset().top - correctionOffset.top + 'px';


					rawDestElement.style.left = destElement.offset().left - correctionOffset.left + 'px';


					d.css('opacity', 0.0); // IE


					if (options.useScaling)
					{


						d.css('transform', 'scale(0.0)');


					}


					d.appendTo($sourceParent);


					animationQueue.push({


						element: $(d),


						animation: animationOptions


					});


				}


			});


			$dest.remove();


			options.enhancement($sourceParent); // Perform custom visual enhancements during the animation


			for (i = 0; i < animationQueue.length; i++)
			{


				animationQueue[i].element.animate(animationQueue[i].animation, options.duration, options.easing, postCallback);


			}


		});


	};


})(jQuery);




// Custom sorting plugin used for quicksand

(function ($)
{

	$.fn.sorted = function (customOptions)
	{

		var options = {

			reversed: false,

			by: function (a) { return a.text(); }

		};

		$.extend(options, customOptions);

		$data = $(this);

		arr = $data.get();

		arr.sort(function (a, b)
		{

			var valA = options.by($(a));

			var valB = options.by($(b));

			if (options.reversed)
			{

				return (valA < valB) ? 1 : (valA > valB) ? -1 : 0;

			} else
			{

				return (valA < valB) ? -1 : (valA > valB) ? 1 : 0;

			}

		});

		return $(arr);

	};


    $.fn.sortedEx = function (customOptions)
	{
		var options = 
        {
			reversed: false,
			by: function (a) { return a.text(); }
		};

		$.extend(options, customOptions);

		$data = $(this);
		arr = $data.get();

        var arrA = arr.Filter(function (a) 
        {
            return options.by($(a)).toString().match(/^\D/);
        });

        var arrB = arr.Filter(function (b) 
        {
            return options.by($(b)).toString().match(/^\d/);
        });

        arrA.sort(function (a, b)
		{
			var valA = options.by($(a));
			var valB = options.by($(b));

			if (options.reversed)
			{
				return (valA < valB) ? 1 : (valA > valB) ? -1 : 0;

			} else
			{
				return (valA < valB) ? -1 : (valA > valB) ? 1 : 0;
			}
		});

        arrB.sort(function (a, b)
		{
			var valA = options.by($(a));
			var valB = options.by($(b));

			if (options.reversed)
			{
				return (valA < valB) ? 1 : (valA > valB) ? -1 : 0;

			} else
			{
				return (valA < valB) ? -1 : (valA > valB) ? 1 : 0;
			}
		});

        return $(arrA.concat(arrB));
	};

})(jQuery);

Array.prototype.Filter = function (compareFunction) 
{
    var filteredArray = new Array();
    for (var i = 0; i < this.length; i++) 
    {
        if (compareFunction(this[i]))
        {
            filteredArray.push(this[i]);
        }
    }
    
    return filteredArray;
};

Array.prototype.alphaSort= function(){
    var itm, L=arguments.length, order=arguments;

    var alphaSort= function(a, b){
        a= a.toLowerCase();
        b= b.toLowerCase();
        if(a== b) return 0;
        return a> b? 1:-1;
    }
    if(!L) return this.sort(alphaSort);

    this.sort(function(a, b){
        var tem= 0,  indx=0;
        while(tem==0 && indx<L){
            itm=order[indx];
            tem= alphaSort(a[itm], b[itm]); 
            indx+=1;        
        }
        return tem;
    });
    return this;
}
