<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki.nerdsgocasual.de/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3ACommon.js</id>
	<title>MediaWiki:Common.js - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.nerdsgocasual.de/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3ACommon.js"/>
	<link rel="alternate" type="text/html" href="https://wiki.nerdsgocasual.de/index.php?title=MediaWiki:Common.js&amp;action=history"/>
	<updated>2026-05-07T20:04:20Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Nerds Go Wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.nerdsgocasual.de/index.php?title=MediaWiki:Common.js&amp;diff=9517&amp;oldid=prev</id>
		<title>IrishWolf: Der Seiteninhalt wurde durch einen anderen Text ersetzt: „/* Das folgende JavaScript wird für alle Benutzer geladen. */“</title>
		<link rel="alternate" type="text/html" href="https://wiki.nerdsgocasual.de/index.php?title=MediaWiki:Common.js&amp;diff=9517&amp;oldid=prev"/>
		<updated>2020-05-13T00:45:31Z</updated>

		<summary type="html">&lt;p&gt;Der Seiteninhalt wurde durch einen anderen Text ersetzt: „&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Das folgende JavaScript wird für alle Benutzer geladen.: &lt;/span&gt;“&lt;/span&gt;&lt;/p&gt;
&lt;a href=&quot;https://wiki.nerdsgocasual.de/index.php?title=MediaWiki:Common.js&amp;amp;diff=9517&amp;amp;oldid=9516&quot;&gt;Änderungen zeigen&lt;/a&gt;</summary>
		<author><name>IrishWolf</name></author>
	</entry>
	<entry>
		<id>https://wiki.nerdsgocasual.de/index.php?title=MediaWiki:Common.js&amp;diff=9516&amp;oldid=prev</id>
		<title>IrishWolf: Sort Function hinzugefügt</title>
		<link rel="alternate" type="text/html" href="https://wiki.nerdsgocasual.de/index.php?title=MediaWiki:Common.js&amp;diff=9516&amp;oldid=prev"/>
		<updated>2020-05-13T00:39:58Z</updated>

		<summary type="html">&lt;p&gt;Sort Function hinzugefügt&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/* Das folgende JavaScript wird für alle Benutzer geladen. */&lt;br /&gt;
&lt;br /&gt;
/***********&lt;br /&gt;
*&lt;br /&gt;
* Sort Functions&lt;br /&gt;
*&lt;br /&gt;
***********/&lt;br /&gt;
&lt;br /&gt;
var Sort = (function(){&lt;br /&gt;
	var sort = {};&lt;br /&gt;
	// Default alpha-numeric sort&lt;br /&gt;
	// --------------------------&lt;br /&gt;
	sort.alphanumeric = function(a,b) {&lt;br /&gt;
		return (a==b)?0:(a&amp;lt;b)?-1:1;&lt;br /&gt;
	};&lt;br /&gt;
	sort['default'] = sort.alphanumeric; // IE chokes on sort.default&lt;br /&gt;
&lt;br /&gt;
	// This conversion is generalized to work for either a decimal separator of , or .&lt;br /&gt;
	sort.numeric_converter = function(separator) {&lt;br /&gt;
		return function(val) {&lt;br /&gt;
			if (typeof(val)==&amp;quot;string&amp;quot;) {&lt;br /&gt;
				val = parseFloat(val.replace(/^[^\d\.]*([\d., ]+).*/g,&amp;quot;$1&amp;quot;).replace(new RegExp(&amp;quot;[^\\\d&amp;quot;+separator+&amp;quot;]&amp;quot;,&amp;quot;g&amp;quot;),'').replace(/,/,'.')) || 0;&lt;br /&gt;
			}&lt;br /&gt;
			return val || 0;&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// Numeric Sort	&lt;br /&gt;
	// ------------&lt;br /&gt;
	sort.numeric = function(a,b) {&lt;br /&gt;
		return sort.numeric.convert(a)-sort.numeric.convert(b);&lt;br /&gt;
	};&lt;br /&gt;
	sort.numeric.convert = sort.numeric_converter(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Numeric Sort	- comma decimal separator&lt;br /&gt;
	// --------------------------------------&lt;br /&gt;
	sort.numeric_comma = function(a,b) {&lt;br /&gt;
		return sort.numeric_comma.convert(a)-sort.numeric_comma.convert(b);&lt;br /&gt;
	};&lt;br /&gt;
	sort.numeric_comma.convert = sort.numeric_converter(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Case-insensitive Sort&lt;br /&gt;
	// ---------------------&lt;br /&gt;
	sort.ignorecase = function(a,b) {&lt;br /&gt;
		return sort.alphanumeric(sort.ignorecase.convert(a),sort.ignorecase.convert(b));&lt;br /&gt;
	};&lt;br /&gt;
	sort.ignorecase.convert = function(val) {&lt;br /&gt;
		if (val==null) { return &amp;quot;&amp;quot;; }&lt;br /&gt;
		return (&amp;quot;&amp;quot;+val).toLowerCase();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// Currency Sort&lt;br /&gt;
	// -------------&lt;br /&gt;
	sort.currency = sort.numeric; // Just treat it as numeric!&lt;br /&gt;
	sort.currency_comma = sort.numeric_comma;&lt;br /&gt;
&lt;br /&gt;
	// Date sort&lt;br /&gt;
	// ---------&lt;br /&gt;
	sort.date = function(a,b) {&lt;br /&gt;
		return sort.numeric(sort.date.convert(a),sort.date.convert(b));&lt;br /&gt;
	};&lt;br /&gt;
	// Convert 2-digit years to 4&lt;br /&gt;
	sort.date.fixYear=function(yr) {&lt;br /&gt;
		yr = +yr;&lt;br /&gt;
		if (yr&amp;lt;50) { yr += 2000; }&lt;br /&gt;
		else if (yr&amp;lt;100) { yr += 1900; }&lt;br /&gt;
		return yr;&lt;br /&gt;
	};&lt;br /&gt;
	sort.date.formats = [&lt;br /&gt;
		// YY[YY]-MM-DD&lt;br /&gt;
		{ re:/(\d{2,4})-(\d{1,2})-(\d{1,2})/ , f:function(x){ return (new Date(sort.date.fixYear(x[1]),+x[2],+x[3])).getTime(); } }&lt;br /&gt;
		// MM/DD/YY[YY] or MM-DD-YY[YY]&lt;br /&gt;
		,{ re:/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/ , f:function(x){ return (new Date(sort.date.fixYear(x[3]),+x[1],+x[2])).getTime(); } }&lt;br /&gt;
		// Any catch-all format that new Date() can handle. This is not reliable except for long formats, for example: 31 Jan 2000 01:23:45 GMT&lt;br /&gt;
		,{ re:/(.*\d{4}.*\d+:\d+\d+.*)/, f:function(x){ var d=new Date(x[1]); if(d){return d.getTime();} } }&lt;br /&gt;
	];&lt;br /&gt;
	sort.date.convert = function(val) {&lt;br /&gt;
		var m,v, f = sort.date.formats;&lt;br /&gt;
		for (var i=0,L=f.length; i&amp;lt;L; i++) {&lt;br /&gt;
			if (m=val.match(f[i].re)) {&lt;br /&gt;
				v=f[i].f(m);&lt;br /&gt;
				if (typeof(v)!=&amp;quot;undefined&amp;quot;) { return v; }&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return 9999999999999; // So non-parsed dates will be last, not first&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	return sort;&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * The main Table namespace&lt;br /&gt;
 */&lt;br /&gt;
var Table = (function(){&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Determine if a reference is defined&lt;br /&gt;
	 */&lt;br /&gt;
	function def(o) {return (typeof o!=&amp;quot;undefined&amp;quot;);};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Determine if an object or class string contains a given class.&lt;br /&gt;
	 */&lt;br /&gt;
	function hasClass(o,name) {&lt;br /&gt;
		return new RegExp(&amp;quot;(^|\\s)&amp;quot;+name+&amp;quot;(\\s|$)&amp;quot;).test(o.className);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Add a class to an object&lt;br /&gt;
	 */&lt;br /&gt;
	function addClass(o,name) {&lt;br /&gt;
		var c = o.className || &amp;quot;&amp;quot;;&lt;br /&gt;
		if (def(c) &amp;amp;&amp;amp; !hasClass(o,name)) {&lt;br /&gt;
			o.className += (c?&amp;quot; &amp;quot;:&amp;quot;&amp;quot;) + name;&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Remove a class from an object&lt;br /&gt;
	 */&lt;br /&gt;
	function removeClass(o,name) {&lt;br /&gt;
		var c = o.className || &amp;quot;&amp;quot;;&lt;br /&gt;
		o.className = c.replace(new RegExp(&amp;quot;(^|\\s)&amp;quot;+name+&amp;quot;(\\s|$)&amp;quot;),&amp;quot;$1&amp;quot;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * For classes that match a given substring, return the rest&lt;br /&gt;
	 */&lt;br /&gt;
	function classValue(o,prefix) {&lt;br /&gt;
		var c = o.className;&lt;br /&gt;
		if (c.match(new RegExp(&amp;quot;(^|\\s)&amp;quot;+prefix+&amp;quot;([^ ]+)&amp;quot;))) {&lt;br /&gt;
			return RegExp.$2;&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Return true if an object is hidden.&lt;br /&gt;
	 * This uses the &amp;quot;russian doll&amp;quot; technique to unwrap itself to the most efficient&lt;br /&gt;
	 * function after the first pass. This avoids repeated feature detection that &lt;br /&gt;
	 * would always fall into the same block of code.&lt;br /&gt;
	 */&lt;br /&gt;
	 function isHidden(o) {&lt;br /&gt;
		if (window.getComputedStyle) {&lt;br /&gt;
			var cs = window.getComputedStyle;&lt;br /&gt;
			return (isHidden = function(o) {&lt;br /&gt;
				return 'none'==cs(o,null).getPropertyValue('display');&lt;br /&gt;
			})(o);&lt;br /&gt;
		}&lt;br /&gt;
		else if (window.currentStyle) {&lt;br /&gt;
			return(isHidden = function(o) {&lt;br /&gt;
				return 'none'==o.currentStyle['display'];&lt;br /&gt;
			})(o);&lt;br /&gt;
		}&lt;br /&gt;
		return (isHidden = function(o) {&lt;br /&gt;
			return 'none'==o.style['display'];&lt;br /&gt;
		})(o);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Get a parent element by tag name, or the original element if it is of the tag type&lt;br /&gt;
	 */&lt;br /&gt;
	function getParent(o,a,b) {&lt;br /&gt;
		if (o!=null &amp;amp;&amp;amp; o.nodeName) {&lt;br /&gt;
			if (o.nodeName==a || (b &amp;amp;&amp;amp; o.nodeName==b)) {&lt;br /&gt;
				return o;&lt;br /&gt;
			}&lt;br /&gt;
			while (o=o.parentNode) {&lt;br /&gt;
				if (o.nodeName &amp;amp;&amp;amp; (o.nodeName==a || (b &amp;amp;&amp;amp; o.nodeName==b))) {&lt;br /&gt;
					return o;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Utility function to copy properties from one object to another&lt;br /&gt;
	 */&lt;br /&gt;
	function copy(o1,o2) {&lt;br /&gt;
		for (var i=2;i&amp;lt;arguments.length; i++) {&lt;br /&gt;
			var a = arguments[i];&lt;br /&gt;
			if (def(o1[a])) {&lt;br /&gt;
				o2[a] = o1[a];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// The table object itself&lt;br /&gt;
	var table = {&lt;br /&gt;
		//Class names used in the code&lt;br /&gt;
		AutoStripeClassName:&amp;quot;table-autostripe&amp;quot;,&lt;br /&gt;
		StripeClassNamePrefix:&amp;quot;table-stripeclass:&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		AutoSortClassName:&amp;quot;table-autosort&amp;quot;,&lt;br /&gt;
		AutoSortColumnPrefix:&amp;quot;table-autosort:&amp;quot;,&lt;br /&gt;
    AutoSortTitle:$j.resource('SortTableFilter_AutoSortTitle'),// modified Jun 10 2010&lt;br /&gt;
		SortedAscendingClassName:&amp;quot;table-sorted-asc&amp;quot;,&lt;br /&gt;
		SortedDescendingClassName:&amp;quot;table-sorted-desc&amp;quot;,&lt;br /&gt;
		SortableClassName:&amp;quot;table-sortable&amp;quot;,&lt;br /&gt;
		SortableColumnPrefix:&amp;quot;table-sortable:&amp;quot;,&lt;br /&gt;
		NoSortClassName:&amp;quot;table-nosort&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		AutoFilterClassName:&amp;quot;table-autofilter&amp;quot;,&lt;br /&gt;
		FilteredClassName:&amp;quot;table-filtered&amp;quot;,&lt;br /&gt;
		FilterableClassName:&amp;quot;table-filterable&amp;quot;,&lt;br /&gt;
		FilteredRowcountPrefix:&amp;quot;table-filtered-rowcount:&amp;quot;,&lt;br /&gt;
		RowcountPrefix:&amp;quot;table-rowcount:&amp;quot;,&lt;br /&gt;
    FilterAllLabel:$j.resource('SortTableFilter_FilterAllLabel'),// modified Jun 10 2010&lt;br /&gt;
&lt;br /&gt;
		AutoPageSizePrefix:&amp;quot;table-autopage:&amp;quot;,&lt;br /&gt;
		AutoPageJumpPrefix:&amp;quot;table-page:&amp;quot;,&lt;br /&gt;
		PageNumberPrefix:&amp;quot;table-page-number:&amp;quot;,&lt;br /&gt;
		PageCountPrefix:&amp;quot;table-page-count:&amp;quot;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * A place to store misc table information, rather than in the table objects themselves&lt;br /&gt;
	 */&lt;br /&gt;
	table.tabledata = {};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Resolve a table given an element reference, and make sure it has a unique ID&lt;br /&gt;
	 */&lt;br /&gt;
	table.uniqueId=1;&lt;br /&gt;
	table.resolve = function(o,args) {&lt;br /&gt;
		if (o!=null &amp;amp;&amp;amp; o.nodeName &amp;amp;&amp;amp; o.nodeName!=&amp;quot;TABLE&amp;quot;) {&lt;br /&gt;
			o = getParent(o,&amp;quot;TABLE&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		if (o==null) { return null; }&lt;br /&gt;
		if (!o.id) {&lt;br /&gt;
			var id = null;&lt;br /&gt;
			do { var id = &amp;quot;TABLE_&amp;quot;+(table.uniqueId++); } &lt;br /&gt;
				while (document.getElementById(id)!=null);&lt;br /&gt;
			o.id = id;&lt;br /&gt;
		}&lt;br /&gt;
		this.tabledata[o.id] = this.tabledata[o.id] || {};&lt;br /&gt;
		if (args) {&lt;br /&gt;
			copy(args,this.tabledata[o.id],&amp;quot;stripeclass&amp;quot;,&amp;quot;ignorehiddenrows&amp;quot;,&amp;quot;useinnertext&amp;quot;,&amp;quot;sorttype&amp;quot;,&amp;quot;col&amp;quot;,&amp;quot;desc&amp;quot;,&amp;quot;page&amp;quot;,&amp;quot;pagesize&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		return o;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Run a function against each cell in a table header or footer, usually &lt;br /&gt;
	 * to add or remove css classes based on sorting, filtering, etc.&lt;br /&gt;
	 */&lt;br /&gt;
	table.processTableCells = function(t, type, func, arg) {&lt;br /&gt;
		t = this.resolve(t);&lt;br /&gt;
		if (t==null) { return; }&lt;br /&gt;
		if (type!=&amp;quot;TFOOT&amp;quot;) {&lt;br /&gt;
			this.processCells(t.tHead, func, arg);&lt;br /&gt;
		}&lt;br /&gt;
		if (type!=&amp;quot;THEAD&amp;quot;) {&lt;br /&gt;
			this.processCells(t.tFoot, func, arg);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Internal method used to process an arbitrary collection of cells.&lt;br /&gt;
	 * Referenced by processTableCells.&lt;br /&gt;
	 * It's done this way to avoid getElementsByTagName() which would also return nested table cells.&lt;br /&gt;
	 */&lt;br /&gt;
	table.processCells = function(section,func,arg) {&lt;br /&gt;
		if (section!=null) {&lt;br /&gt;
			if (section.rows &amp;amp;&amp;amp; section.rows.length &amp;amp;&amp;amp; section.rows.length&amp;gt;0) { &lt;br /&gt;
				var rows = section.rows;&lt;br /&gt;
				for (var j=0,L2=rows.length; j&amp;lt;L2; j++) { &lt;br /&gt;
					var row = rows[j];&lt;br /&gt;
					if (row.cells &amp;amp;&amp;amp; row.cells.length &amp;amp;&amp;amp; row.cells.length&amp;gt;0) {&lt;br /&gt;
						var cells = row.cells;&lt;br /&gt;
						for (var k=0,L3=cells.length; k&amp;lt;L3; k++) {&lt;br /&gt;
							var cellsK = cells[k];&lt;br /&gt;
							func.call(this,cellsK,arg);&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Get the cellIndex value for a cell. This is only needed because of a Safari&lt;br /&gt;
	 * bug that causes cellIndex to exist but always be 0.&lt;br /&gt;
	 * Rather than feature-detecting each time it is called, the function will&lt;br /&gt;
	 * re-write itself the first time it is called.&lt;br /&gt;
	 */&lt;br /&gt;
	table.getCellIndex = function(td) {&lt;br /&gt;
		var tr = td.parentNode;&lt;br /&gt;
		var cells = tr.cells;&lt;br /&gt;
		if (cells &amp;amp;&amp;amp; cells.length) {&lt;br /&gt;
			if (cells.length&amp;gt;1 &amp;amp;&amp;amp; cells[cells.length-1].cellIndex&amp;gt;0) {&lt;br /&gt;
				// Define the new function, overwrite the one we're running now, and then run the new one&lt;br /&gt;
				(this.getCellIndex = function(td) {&lt;br /&gt;
					return td.cellIndex;&lt;br /&gt;
				})(td);&lt;br /&gt;
			}&lt;br /&gt;
			// Safari will always go through this slower block every time. Oh well.&lt;br /&gt;
			for (var i=0,L=cells.length; i&amp;lt;L; i++) {&lt;br /&gt;
				if (tr.cells[i]==td) {&lt;br /&gt;
					return i;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return 0;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * A map of node names and how to convert them into their &amp;quot;value&amp;quot; for sorting, filtering, etc.&lt;br /&gt;
	 * These are put here so it is extensible.&lt;br /&gt;
	 */&lt;br /&gt;
	table.nodeValue = {&lt;br /&gt;
		'INPUT':function(node) { &lt;br /&gt;
			if (def(node.value) &amp;amp;&amp;amp; node.type &amp;amp;&amp;amp; ((node.type!=&amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; node.type!=&amp;quot;radio&amp;quot;) || node.checked)) {&lt;br /&gt;
				return node.value;&lt;br /&gt;
			}&lt;br /&gt;
			return &amp;quot;&amp;quot;;&lt;br /&gt;
		},&lt;br /&gt;
		'SELECT':function(node) {&lt;br /&gt;
			if (node.selectedIndex&amp;gt;=0 &amp;amp;&amp;amp; node.options) {&lt;br /&gt;
				// Sort select elements by the visible text&lt;br /&gt;
				return node.options[node.selectedIndex].text;&lt;br /&gt;
			}&lt;br /&gt;
			return &amp;quot;&amp;quot;;&lt;br /&gt;
		},&lt;br /&gt;
		'IMG':function(node) {&lt;br /&gt;
			return node.name || &amp;quot;&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Get the text value of a cell. Only use innerText if explicitly told to, because &lt;br /&gt;
	 * otherwise we want to be able to handle sorting on inputs and other types&lt;br /&gt;
	 */&lt;br /&gt;
	table.getCellValue = function(td,useInnerText) {&lt;br /&gt;
		if (useInnerText &amp;amp;&amp;amp; def(td.innerText)) {&lt;br /&gt;
			return td.innerText;&lt;br /&gt;
		}&lt;br /&gt;
		if (!td.childNodes) { &lt;br /&gt;
			return &amp;quot;&amp;quot;; &lt;br /&gt;
		}&lt;br /&gt;
		var childNodes=td.childNodes;&lt;br /&gt;
		var ret = &amp;quot;&amp;quot;;&lt;br /&gt;
		for (var i=0,L=childNodes.length; i&amp;lt;L; i++) {&lt;br /&gt;
			var node = childNodes[i];&lt;br /&gt;
			var type = node.nodeType;&lt;br /&gt;
			// In order to get realistic sort results, we need to treat some elements in a special way.&lt;br /&gt;
			// These behaviors are defined in the nodeValue() object, keyed by node name&lt;br /&gt;
			if (type==1) {&lt;br /&gt;
				var nname = node.nodeName;&lt;br /&gt;
				if (this.nodeValue[nname]) {&lt;br /&gt;
					ret += this.nodeValue[nname](node);&lt;br /&gt;
				}&lt;br /&gt;
				else {&lt;br /&gt;
					ret += this.getCellValue(node);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			else if (type==3) {&lt;br /&gt;
				if (def(node.innerText)) {&lt;br /&gt;
					ret += node.innerText;&lt;br /&gt;
				}&lt;br /&gt;
				else if (def(node.nodeValue)) {&lt;br /&gt;
					ret += node.nodeValue;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Consider colspan and rowspan values in table header cells to calculate the actual cellIndex&lt;br /&gt;
	 * of a given cell. This is necessary because if the first cell in row 0 has a rowspan of 2, &lt;br /&gt;
	 * then the first cell in row 1 will have a cellIndex of 0 rather than 1, even though it really&lt;br /&gt;
	 * starts in the second column rather than the first.&lt;br /&gt;
	 * See: http://www.javascripttoolbox.com/temp/table_cellindex.html&lt;br /&gt;
	 */&lt;br /&gt;
	table.tableHeaderIndexes = {};&lt;br /&gt;
	table.getActualCellIndex = function(tableCellObj) {&lt;br /&gt;
		if (!def(tableCellObj.cellIndex)) { return null; }&lt;br /&gt;
		var tableObj = getParent(tableCellObj,&amp;quot;TABLE&amp;quot;);&lt;br /&gt;
		var cellCoordinates = tableCellObj.parentNode.rowIndex+&amp;quot;-&amp;quot;+this.getCellIndex(tableCellObj);&lt;br /&gt;
&lt;br /&gt;
		// If it has already been computed, return the answer from the lookup table&lt;br /&gt;
		if (def(this.tableHeaderIndexes[tableObj.id])) {&lt;br /&gt;
			return this.tableHeaderIndexes[tableObj.id][cellCoordinates];      &lt;br /&gt;
		} &lt;br /&gt;
&lt;br /&gt;
		var matrix = [];&lt;br /&gt;
		this.tableHeaderIndexes[tableObj.id] = {};&lt;br /&gt;
		var thead = getParent(tableCellObj,&amp;quot;THEAD&amp;quot;);&lt;br /&gt;
		var trs = thead.getElementsByTagName('TR');&lt;br /&gt;
&lt;br /&gt;
		// Loop thru every tr and every cell in the tr, building up a 2-d array &amp;quot;grid&amp;quot; that gets&lt;br /&gt;
		// populated with an &amp;quot;x&amp;quot; for each space that a cell takes up. If the first cell is colspan&lt;br /&gt;
		// 2, it will fill in values [0] and [1] in the first array, so that the second cell will&lt;br /&gt;
		// find the first empty cell in the first row (which will be [2]) and know that this is&lt;br /&gt;
		// where it sits, rather than its internal .cellIndex value of [1].&lt;br /&gt;
		for (var i=0; i&amp;lt;trs.length; i++) {&lt;br /&gt;
			var cells = trs[i].cells;&lt;br /&gt;
			for (var j=0; j&amp;lt;cells.length; j++) {&lt;br /&gt;
				var c = cells[j];&lt;br /&gt;
				var rowIndex = c.parentNode.rowIndex;&lt;br /&gt;
				var cellId = rowIndex+&amp;quot;-&amp;quot;+this.getCellIndex(c);&lt;br /&gt;
				var rowSpan = c.rowSpan || 1;&lt;br /&gt;
				var colSpan = c.colSpan || 1;&lt;br /&gt;
				var firstAvailCol;&lt;br /&gt;
				if(!def(matrix[rowIndex])) { &lt;br /&gt;
					matrix[rowIndex] = []; &lt;br /&gt;
				}&lt;br /&gt;
				var m = matrix[rowIndex];&lt;br /&gt;
				// Find first available column in the first row&lt;br /&gt;
				for (var k=0; k&amp;lt;m.length+1; k++) {&lt;br /&gt;
					if (!def(m[k])) {&lt;br /&gt;
						firstAvailCol = k;&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				this.tableHeaderIndexes[tableObj.id][cellId] = firstAvailCol;&lt;br /&gt;
				for (var k=rowIndex; k&amp;lt;rowIndex+rowSpan; k++) {&lt;br /&gt;
					if(!def(matrix[k])) { &lt;br /&gt;
						matrix[k] = []; &lt;br /&gt;
					}&lt;br /&gt;
					var matrixrow = matrix[k];&lt;br /&gt;
					for (var l=firstAvailCol; l&amp;lt;firstAvailCol+colSpan; l++) {&lt;br /&gt;
						matrixrow[l] = &amp;quot;x&amp;quot;;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		// Store the map so future lookups are fast.&lt;br /&gt;
		return this.tableHeaderIndexes[tableObj.id][cellCoordinates];&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Sort all rows in each TBODY (tbodies are sorted independent of each other)&lt;br /&gt;
	 */&lt;br /&gt;
	table.sort = function(o,args) {&lt;br /&gt;
		var t, tdata, sortconvert=null;&lt;br /&gt;
		// Allow for a simple passing of sort type as second parameter&lt;br /&gt;
		if (typeof(args)==&amp;quot;function&amp;quot;) {&lt;br /&gt;
			args={sorttype:args};&lt;br /&gt;
		}&lt;br /&gt;
		args = args || {};&lt;br /&gt;
&lt;br /&gt;
		// If no col is specified, deduce it from the object sent in&lt;br /&gt;
		if (!def(args.col)) { &lt;br /&gt;
			args.col = this.getActualCellIndex(o) || 0; &lt;br /&gt;
		}&lt;br /&gt;
		// If no sort type is specified, default to the default sort&lt;br /&gt;
		args.sorttype = args.sorttype || Sort['default'];&lt;br /&gt;
&lt;br /&gt;
		// Resolve the table&lt;br /&gt;
		t = this.resolve(o,args);&lt;br /&gt;
		tdata = this.tabledata[t.id];&lt;br /&gt;
&lt;br /&gt;
		// If we are sorting on the same column as last time, flip the sort direction&lt;br /&gt;
		if (def(tdata.lastcol) &amp;amp;&amp;amp; tdata.lastcol==tdata.col &amp;amp;&amp;amp; def(tdata.lastdesc)) {&lt;br /&gt;
			tdata.desc = !tdata.lastdesc;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			tdata.desc = !!args.desc;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Store the last sorted column so clicking again will reverse the sort order&lt;br /&gt;
		tdata.lastcol=tdata.col;&lt;br /&gt;
		tdata.lastdesc=!!tdata.desc;&lt;br /&gt;
&lt;br /&gt;
		// If a sort conversion function exists, pre-convert cell values and then use a plain alphanumeric sort&lt;br /&gt;
		var sorttype = tdata.sorttype;&lt;br /&gt;
		if (typeof(sorttype.convert)==&amp;quot;function&amp;quot;) {&lt;br /&gt;
			sortconvert=tdata.sorttype.convert;&lt;br /&gt;
			sorttype=Sort.alphanumeric;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Loop through all THEADs and remove sorted class names, then re-add them for the col&lt;br /&gt;
		// that is being sorted&lt;br /&gt;
		this.processTableCells(t,&amp;quot;THEAD&amp;quot;,&lt;br /&gt;
			function(cell) {&lt;br /&gt;
				if (hasClass(cell,this.SortableClassName)) {&lt;br /&gt;
					removeClass(cell,this.SortedAscendingClassName);&lt;br /&gt;
					removeClass(cell,this.SortedDescendingClassName);&lt;br /&gt;
					// If the computed colIndex of the cell equals the sorted colIndex, flag it as sorted&lt;br /&gt;
					if (tdata.col==table.getActualCellIndex(cell) &amp;amp;&amp;amp; (classValue(cell,table.SortableClassName))) {&lt;br /&gt;
						addClass(cell,tdata.desc?this.SortedAscendingClassName:this.SortedDescendingClassName);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
		// Sort each tbody independently&lt;br /&gt;
		var bodies = t.tBodies;&lt;br /&gt;
		if (bodies==null || bodies.length==0) { return; }&lt;br /&gt;
&lt;br /&gt;
		// Define a new sort function to be called to consider descending or not&lt;br /&gt;
		var newSortFunc = (tdata.desc)?&lt;br /&gt;
			function(a,b){return sorttype(b[0],a[0]);}&lt;br /&gt;
			:function(a,b){return sorttype(a[0],b[0]);};&lt;br /&gt;
&lt;br /&gt;
		var useinnertext=!!tdata.useinnertext;&lt;br /&gt;
		var col = tdata.col;&lt;br /&gt;
&lt;br /&gt;
		for (var i=0,L=bodies.length; i&amp;lt;L; i++) {&lt;br /&gt;
			var tb = bodies[i], tbrows = tb.rows, rows = [];&lt;br /&gt;
&lt;br /&gt;
			// Allow tbodies to request that they not be sorted&lt;br /&gt;
			if(!hasClass(tb,table.NoSortClassName)) {&lt;br /&gt;
				// Create a separate array which will store the converted values and refs to the&lt;br /&gt;
				// actual rows. This is the array that will be sorted.&lt;br /&gt;
				var cRow, cRowIndex=0;&lt;br /&gt;
				if (cRow=tbrows[cRowIndex]){&lt;br /&gt;
					// Funky loop style because it's considerably faster in IE&lt;br /&gt;
					do {&lt;br /&gt;
						if (rowCells = cRow.cells) {&lt;br /&gt;
							var cellValue = (col&amp;lt;rowCells.length)?this.getCellValue(rowCells[col],useinnertext):null;&lt;br /&gt;
							if (sortconvert) cellValue = sortconvert(cellValue);&lt;br /&gt;
							rows[cRowIndex] = [cellValue,tbrows[cRowIndex]];&lt;br /&gt;
						}&lt;br /&gt;
					} while (cRow=tbrows[++cRowIndex])&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Do the actual sorting&lt;br /&gt;
				rows.sort(newSortFunc);&lt;br /&gt;
&lt;br /&gt;
				// Move the rows to the correctly sorted order. Appending an existing DOM object just moves it!&lt;br /&gt;
				cRowIndex=0;&lt;br /&gt;
				var displayedCount=0;&lt;br /&gt;
				var f=[removeClass,addClass];&lt;br /&gt;
				if (cRow=rows[cRowIndex]){&lt;br /&gt;
					do { &lt;br /&gt;
						tb.appendChild(cRow[1]); &lt;br /&gt;
					} while (cRow=rows[++cRowIndex])&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// If paging is enabled on the table, then we need to re-page because the order of rows has changed!&lt;br /&gt;
		if (tdata.pagesize) {&lt;br /&gt;
			this.page(t); // This will internally do the striping&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			// Re-stripe if a class name was supplied&lt;br /&gt;
			if (tdata.stripeclass) {&lt;br /&gt;
				this.stripe(t,tdata.stripeclass,!!tdata.ignorehiddenrows);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	* Apply a filter to rows in a table and hide those that do not match.&lt;br /&gt;
	*/&lt;br /&gt;
	table.filter = function(o,filters,args) {&lt;br /&gt;
		var cell;&lt;br /&gt;
		args = args || {};&lt;br /&gt;
&lt;br /&gt;
		var t = this.resolve(o,args);&lt;br /&gt;
		var tdata = this.tabledata[t.id];&lt;br /&gt;
&lt;br /&gt;
		// If new filters were passed in, apply them to the table's list of filters&lt;br /&gt;
		if (!filters) {&lt;br /&gt;
			// If a null or blank value was sent in for 'filters' then that means reset the table to no filters&lt;br /&gt;
			tdata.filters = null;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			// Allow for passing a select list in as the filter, since this is common design&lt;br /&gt;
			if (filters.nodeName==&amp;quot;SELECT&amp;quot; &amp;amp;&amp;amp; filters.type==&amp;quot;select-one&amp;quot; &amp;amp;&amp;amp; filters.selectedIndex&amp;gt;-1) {&lt;br /&gt;
				filters={ 'filter':filters.options[filters.selectedIndex].value };&lt;br /&gt;
			}&lt;br /&gt;
			// Also allow for a regular input&lt;br /&gt;
			if (filters.nodeName==&amp;quot;INPUT&amp;quot; &amp;amp;&amp;amp; filters.type==&amp;quot;text&amp;quot;) {&lt;br /&gt;
				filters={ 'filter':&amp;quot;/^&amp;quot;+filters.value+&amp;quot;/&amp;quot; };&lt;br /&gt;
			}&lt;br /&gt;
			// Force filters to be an array&lt;br /&gt;
			if (typeof(filters)==&amp;quot;object&amp;quot; &amp;amp;&amp;amp; !filters.length) {&lt;br /&gt;
				filters = [filters];&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// Convert regular expression strings to RegExp objects and function strings to function objects&lt;br /&gt;
			for (var i=0,L=filters.length; i&amp;lt;L; i++) {&lt;br /&gt;
				var filter = filters[i];&lt;br /&gt;
				if (typeof(filter.filter)==&amp;quot;string&amp;quot;) {&lt;br /&gt;
					// If a filter string is like &amp;quot;/expr/&amp;quot; then turn it into a Regex&lt;br /&gt;
					if (filter.filter.match(/^\/(.*)\/$/)) {&lt;br /&gt;
						filter.filter = new RegExp(RegExp.$1);&lt;br /&gt;
						filter.filter.regex=true;&lt;br /&gt;
					}&lt;br /&gt;
					// If filter string is like &amp;quot;function (x) { ... }&amp;quot; then turn it into a function&lt;br /&gt;
					else if (filter.filter.match(/^function\s*\(([^\)]*)\)\s*\{(.*)}\s*$/)) {&lt;br /&gt;
						filter.filter = Function(RegExp.$1,RegExp.$2);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				// If some non-table object was passed in rather than a 'col' value, resolve it &lt;br /&gt;
				// and assign it's column index to the filter if it doesn't have one. This way, &lt;br /&gt;
				// passing in a cell reference or a select object etc instead of a table object &lt;br /&gt;
				// will automatically set the correct column to filter.&lt;br /&gt;
				if (filter &amp;amp;&amp;amp; !def(filter.col) &amp;amp;&amp;amp; (cell=getParent(o,&amp;quot;TD&amp;quot;,&amp;quot;TH&amp;quot;))) {&lt;br /&gt;
					filter.col = this.getCellIndex(cell);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Apply the passed-in filters to the existing list of filters for the table, removing those that have a filter of null or &amp;quot;&amp;quot;&lt;br /&gt;
				if ((!filter || !filter.filter) &amp;amp;&amp;amp; tdata.filters) {&lt;br /&gt;
					delete tdata.filters[filter.col];&lt;br /&gt;
				}&lt;br /&gt;
				else {&lt;br /&gt;
					tdata.filters = tdata.filters || {};&lt;br /&gt;
					tdata.filters[filter.col] = filter.filter;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// If no more filters are left, then make sure to empty out the filters object&lt;br /&gt;
			for (var j in tdata.filters) { var keep = true; }&lt;br /&gt;
			if (!keep) {&lt;br /&gt;
				tdata.filters = null;&lt;br /&gt;
			}&lt;br /&gt;
		}		&lt;br /&gt;
		// Everything's been setup, so now scrape the table rows&lt;br /&gt;
		return table.scrape(o);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * &amp;quot;Page&amp;quot; a table by showing only a subset of the rows&lt;br /&gt;
	 */&lt;br /&gt;
	table.page = function(t,page,args) {&lt;br /&gt;
		args = args || {};&lt;br /&gt;
		if (def(page)) { args.page = page; }&lt;br /&gt;
		return table.scrape(t,args);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Jump forward or back any number of pages&lt;br /&gt;
	 */&lt;br /&gt;
	table.pageJump = function(t,count,args) {&lt;br /&gt;
		t = this.resolve(t,args);&lt;br /&gt;
		return this.page(t,(table.tabledata[t.id].page||0)+count,args);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Go to the next page of a paged table&lt;br /&gt;
	 */	&lt;br /&gt;
	table.pageNext = function(t,args) {&lt;br /&gt;
		return this.pageJump(t,1,args);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Go to the previous page of a paged table&lt;br /&gt;
	 */	&lt;br /&gt;
	table.pagePrevious = function(t,args) {&lt;br /&gt;
		return this.pageJump(t,-1,args);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	* Scrape a table to either hide or show each row based on filters and paging&lt;br /&gt;
	*/&lt;br /&gt;
	table.scrape = function(o,args) {&lt;br /&gt;
		var col,cell,filterList,filterReset=false,filter;&lt;br /&gt;
		var page,pagesize,pagestart,pageend;&lt;br /&gt;
		var unfilteredrows=[],unfilteredrowcount=0,totalrows=0;&lt;br /&gt;
		var t,tdata,row,hideRow;&lt;br /&gt;
		args = args || {};&lt;br /&gt;
&lt;br /&gt;
		// Resolve the table object&lt;br /&gt;
		t = this.resolve(o,args);&lt;br /&gt;
		tdata = this.tabledata[t.id];&lt;br /&gt;
&lt;br /&gt;
		// Setup for Paging&lt;br /&gt;
		var page = tdata.page;&lt;br /&gt;
		if (def(page)) {&lt;br /&gt;
			// Don't let the page go before the beginning&lt;br /&gt;
			if (page&amp;lt;0) { tdata.page=page=0; }&lt;br /&gt;
			pagesize = tdata.pagesize || 25; // 25=arbitrary default&lt;br /&gt;
			pagestart = page*pagesize+1;&lt;br /&gt;
			pageend = pagestart + pagesize - 1;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Scrape each row of each tbody&lt;br /&gt;
		var bodies = t.tBodies;&lt;br /&gt;
		if (bodies==null || bodies.length==0) { return; }&lt;br /&gt;
		for (var i=0,L=bodies.length; i&amp;lt;L; i++) {&lt;br /&gt;
			var tb = bodies[i];&lt;br /&gt;
			for (var j=0,L2=tb.rows.length; j&amp;lt;L2; j++) {&lt;br /&gt;
				row = tb.rows[j];&lt;br /&gt;
				hideRow = false;&lt;br /&gt;
&lt;br /&gt;
				// Test if filters will hide the row&lt;br /&gt;
				if (tdata.filters &amp;amp;&amp;amp; row.cells) {&lt;br /&gt;
					var cells = row.cells;&lt;br /&gt;
					var cellsLength = cells.length;&lt;br /&gt;
					// Test each filter&lt;br /&gt;
					for (col in tdata.filters) {&lt;br /&gt;
						if (!hideRow) {&lt;br /&gt;
							filter = tdata.filters[col];&lt;br /&gt;
							if (filter &amp;amp;&amp;amp; col&amp;lt;cellsLength) {&lt;br /&gt;
								var val = this.getCellValue(cells[col]);&lt;br /&gt;
								if (filter.regex &amp;amp;&amp;amp; val.search) {&lt;br /&gt;
									hideRow=(val.search(filter)&amp;lt;0);&lt;br /&gt;
								}&lt;br /&gt;
								else if (typeof(filter)==&amp;quot;function&amp;quot;) {&lt;br /&gt;
									hideRow=!filter(val,cells[col]);&lt;br /&gt;
								}&lt;br /&gt;
								else {&lt;br /&gt;
									hideRow = (val!=filter);&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Keep track of the total rows scanned and the total runs _not_ filtered out&lt;br /&gt;
				totalrows++;&lt;br /&gt;
				if (!hideRow) {&lt;br /&gt;
					unfilteredrowcount++;&lt;br /&gt;
					if (def(page)) {&lt;br /&gt;
						// Temporarily keep an array of unfiltered rows in case the page we're on goes past&lt;br /&gt;
						// the last page and we need to back up. Don't want to filter again!&lt;br /&gt;
						unfilteredrows.push(row);&lt;br /&gt;
						if (unfilteredrowcount&amp;lt;pagestart || unfilteredrowcount&amp;gt;pageend) {&lt;br /&gt;
							hideRow = true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				row.style.display = hideRow?&amp;quot;none&amp;quot;:&amp;quot;&amp;quot;;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (def(page)) {&lt;br /&gt;
			// Check to see if filtering has put us past the requested page index. If it has, &lt;br /&gt;
			// then go back to the last page and show it.&lt;br /&gt;
			if (pagestart&amp;gt;=unfilteredrowcount) {&lt;br /&gt;
				pagestart = unfilteredrowcount-(unfilteredrowcount%pagesize);&lt;br /&gt;
				tdata.page = page = pagestart/pagesize;&lt;br /&gt;
				for (var i=pagestart,L=unfilteredrows.length; i&amp;lt;L; i++) {&lt;br /&gt;
					unfilteredrows[i].style.display=&amp;quot;&amp;quot;;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Loop through all THEADs and add/remove filtered class names&lt;br /&gt;
		this.processTableCells(t,&amp;quot;THEAD&amp;quot;,&lt;br /&gt;
			function(c) {&lt;br /&gt;
				((tdata.filters &amp;amp;&amp;amp; def(tdata.filters[table.getCellIndex(c)]) &amp;amp;&amp;amp; hasClass(c,table.FilterableClassName))?addClass:removeClass)(c,table.FilteredClassName);&lt;br /&gt;
			}&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
		// Stripe the table if necessary&lt;br /&gt;
		if (tdata.stripeclass) {&lt;br /&gt;
			this.stripe(t);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Calculate some values to be returned for info and updating purposes&lt;br /&gt;
		var pagecount = Math.floor(unfilteredrowcount/pagesize)+1;&lt;br /&gt;
		if (def(page)) {&lt;br /&gt;
			// Update the page number/total containers if they exist&lt;br /&gt;
			if (tdata.container_number) {&lt;br /&gt;
				tdata.container_number.innerHTML = page+1;&lt;br /&gt;
			}&lt;br /&gt;
			if (tdata.container_count) {&lt;br /&gt;
				tdata.container_count.innerHTML = pagecount;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Update the row count containers if they exist&lt;br /&gt;
		if (tdata.container_filtered_count) {&lt;br /&gt;
			tdata.container_filtered_count.innerHTML = unfilteredrowcount;&lt;br /&gt;
		}&lt;br /&gt;
		if (tdata.container_all_count) {&lt;br /&gt;
			tdata.container_all_count.innerHTML = totalrows;&lt;br /&gt;
		}&lt;br /&gt;
		return { 'data':tdata, 'unfilteredcount':unfilteredrowcount, 'total':totalrows, 'pagecount':pagecount, 'page':page, 'pagesize':pagesize };&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Shade alternate rows, aka Stripe the table.&lt;br /&gt;
	 */&lt;br /&gt;
	table.stripe = function(t,className,args) { &lt;br /&gt;
		args = args || {};&lt;br /&gt;
		args.stripeclass = className;&lt;br /&gt;
&lt;br /&gt;
		t = this.resolve(t,args);&lt;br /&gt;
		var tdata = this.tabledata[t.id];&lt;br /&gt;
&lt;br /&gt;
		var bodies = t.tBodies;&lt;br /&gt;
		if (bodies==null || bodies.length==0) { &lt;br /&gt;
			return; &lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		className = tdata.stripeclass;&lt;br /&gt;
		// Cache a shorter, quicker reference to either the remove or add class methods&lt;br /&gt;
		var f=[removeClass,addClass];&lt;br /&gt;
		for (var i=0,L=bodies.length; i&amp;lt;L; i++) {&lt;br /&gt;
			var tb = bodies[i], tbrows = tb.rows, cRowIndex=0, cRow, displayedCount=0;&lt;br /&gt;
			if (cRow=tbrows[cRowIndex]){&lt;br /&gt;
				// The ignorehiddenrows test is pulled out of the loop for a slight speed increase.&lt;br /&gt;
				// Makes a bigger difference in FF than in IE.&lt;br /&gt;
				// In this case, speed always wins over brevity!&lt;br /&gt;
				if (tdata.ignoreHiddenRows) {&lt;br /&gt;
					do {&lt;br /&gt;
						f[displayedCount++%2](cRow,className);&lt;br /&gt;
					} while (cRow=tbrows[++cRowIndex])&lt;br /&gt;
				}&lt;br /&gt;
				else {&lt;br /&gt;
					do {&lt;br /&gt;
						if (!isHidden(cRow)) {&lt;br /&gt;
							f[displayedCount++%2](cRow,className);&lt;br /&gt;
						}&lt;br /&gt;
					} while (cRow=tbrows[++cRowIndex])&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Build up a list of unique values in a table column&lt;br /&gt;
	 */&lt;br /&gt;
	table.getUniqueColValues = function(t,col) {&lt;br /&gt;
		var values={}, bodies = this.resolve(t).tBodies;&lt;br /&gt;
		for (var i=0,L=bodies.length; i&amp;lt;L; i++) {&lt;br /&gt;
			var tbody = bodies[i];&lt;br /&gt;
			for (var r=0,L2=tbody.rows.length; r&amp;lt;L2; r++) {&lt;br /&gt;
				values[this.getCellValue(tbody.rows[r].cells[col])] = true;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		var valArray = [];&lt;br /&gt;
		for (var val in values) {&lt;br /&gt;
			valArray.push(val);&lt;br /&gt;
		}&lt;br /&gt;
		return valArray.sort();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Scan the document on load and add sorting, filtering, paging etc ability automatically&lt;br /&gt;
	 * based on existence of class names on the table and cells.&lt;br /&gt;
	 */&lt;br /&gt;
	table.auto = function(args) {&lt;br /&gt;
		var cells = [], tables = document.getElementsByTagName(&amp;quot;TABLE&amp;quot;);&lt;br /&gt;
		var val,tdata;&lt;br /&gt;
		if (tables!=null) {&lt;br /&gt;
			for (var i=0,L=tables.length; i&amp;lt;L; i++) {&lt;br /&gt;
				var t = table.resolve(tables[i]);&lt;br /&gt;
				tdata = table.tabledata[t.id];&lt;br /&gt;
				if (val=classValue(t,table.StripeClassNamePrefix)) {&lt;br /&gt;
					tdata.stripeclass=val;&lt;br /&gt;
				}&lt;br /&gt;
				// Do auto-filter if necessary&lt;br /&gt;
				if (hasClass(t,table.AutoFilterClassName)) {&lt;br /&gt;
					table.autofilter(t);&lt;br /&gt;
				}&lt;br /&gt;
				// Do auto-page if necessary&lt;br /&gt;
				if (val = classValue(t,table.AutoPageSizePrefix)) {&lt;br /&gt;
					table.autopage(t,{'pagesize':+val});&lt;br /&gt;
				}&lt;br /&gt;
				// Do auto-sort if necessary&lt;br /&gt;
				if ((val = classValue(t,table.AutoSortColumnPrefix)) || (hasClass(t,table.AutoSortClassName))) {&lt;br /&gt;
					table.autosort(t,{'col':(val==null)?null:+val});&lt;br /&gt;
				}&lt;br /&gt;
				// Do auto-stripe if necessary&lt;br /&gt;
				if (tdata.stripeclass &amp;amp;&amp;amp; hasClass(t,table.AutoStripeClassName)) {&lt;br /&gt;
					table.stripe(t);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Add sorting functionality to a table header cell&lt;br /&gt;
	 */&lt;br /&gt;
	table.autosort = function(t,args) {&lt;br /&gt;
		t = this.resolve(t,args);&lt;br /&gt;
		var tdata = this.tabledata[t.id];&lt;br /&gt;
		this.processTableCells(t, &amp;quot;THEAD&amp;quot;, function(c) {&lt;br /&gt;
			var type = classValue(c,table.SortableColumnPrefix);&lt;br /&gt;
			if (type!=null) {&lt;br /&gt;
				type = type || &amp;quot;default&amp;quot;;&lt;br /&gt;
				c.title =c.title || table.AutoSortTitle;&lt;br /&gt;
				addClass(c,table.SortableClassName);&lt;br /&gt;
				c.onclick = Function(&amp;quot;&amp;quot;,&amp;quot;Table.sort(this,{'sorttype':Sort['&amp;quot;+type+&amp;quot;']})&amp;quot;);&lt;br /&gt;
				// If we are going to auto sort on a column, we need to keep track of what kind of sort it will be&lt;br /&gt;
				if (args.col!=null) {&lt;br /&gt;
					if (args.col==table.getActualCellIndex(c)) {&lt;br /&gt;
						tdata.sorttype=Sort['&amp;quot;+type+&amp;quot;'];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		} );&lt;br /&gt;
		if (args.col!=null) {&lt;br /&gt;
			table.sort(t,args);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Add paging functionality to a table &lt;br /&gt;
	 */&lt;br /&gt;
	table.autopage = function(t,args) {&lt;br /&gt;
		t = this.resolve(t,args);&lt;br /&gt;
		var tdata = this.tabledata[t.id];&lt;br /&gt;
		if (tdata.pagesize) {&lt;br /&gt;
			this.processTableCells(t, &amp;quot;THEAD,TFOOT&amp;quot;, function(c) {&lt;br /&gt;
				var type = classValue(c,table.AutoPageJumpPrefix);&lt;br /&gt;
				if (type==&amp;quot;next&amp;quot;) { type = 1; }&lt;br /&gt;
				else if (type==&amp;quot;previous&amp;quot;) { type = -1; }&lt;br /&gt;
				if (type!=null) {&lt;br /&gt;
					c.onclick = Function(&amp;quot;&amp;quot;,&amp;quot;Table.pageJump(this,&amp;quot;+type+&amp;quot;)&amp;quot;);&lt;br /&gt;
				}&lt;br /&gt;
			} );&lt;br /&gt;
			if (val = classValue(t,table.PageNumberPrefix)) {&lt;br /&gt;
				tdata.container_number = document.getElementById(val);&lt;br /&gt;
			}&lt;br /&gt;
			if (val = classValue(t,table.PageCountPrefix)) {&lt;br /&gt;
				tdata.container_count = document.getElementById(val);&lt;br /&gt;
			}&lt;br /&gt;
			return table.page(t,0,args);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * A util function to cancel bubbling of clicks on filter dropdowns&lt;br /&gt;
	 */&lt;br /&gt;
	table.cancelBubble = function(e) {&lt;br /&gt;
		e = e || window.event;&lt;br /&gt;
		if (typeof(e.stopPropagation)==&amp;quot;function&amp;quot;) { e.stopPropagation(); } &lt;br /&gt;
		if (def(e.cancelBubble)) { e.cancelBubble = true; }&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Auto-filter a table&lt;br /&gt;
	 */&lt;br /&gt;
	table.autofilter = function(t,args) {&lt;br /&gt;
		args = args || {};&lt;br /&gt;
		t = this.resolve(t,args);&lt;br /&gt;
		var tdata = this.tabledata[t.id],val;&lt;br /&gt;
		table.processTableCells(t, &amp;quot;THEAD&amp;quot;, function(cell) {&lt;br /&gt;
			if (hasClass(cell,table.FilterableClassName)) {&lt;br /&gt;
				var cellIndex = table.getCellIndex(cell);&lt;br /&gt;
				var colValues = table.getUniqueColValues(t,cellIndex);&lt;br /&gt;
				if (colValues.length&amp;gt;0) {&lt;br /&gt;
					if (typeof(args.insert)==&amp;quot;function&amp;quot;) {&lt;br /&gt;
						func.insert(cell,colValues);&lt;br /&gt;
					}&lt;br /&gt;
					else {&lt;br /&gt;
						var sel = '&amp;lt;select onchange=&amp;quot;Table.filter(this,this)&amp;quot; onclick=&amp;quot;Table.cancelBubble(event)&amp;quot; class=&amp;quot;'+table.AutoFilterClassName+'&amp;quot;&amp;gt;&amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;'+table.FilterAllLabel+'&amp;lt;/option&amp;gt;';&lt;br /&gt;
						for (var i=0; i&amp;lt;colValues.length; i++) {&lt;br /&gt;
							sel += '&amp;lt;option value=&amp;quot;'+colValues[i]+'&amp;quot;&amp;gt;'+colValues[i]+'&amp;lt;/option&amp;gt;';&lt;br /&gt;
						}&lt;br /&gt;
						sel += '&amp;lt;/select&amp;gt;';&lt;br /&gt;
            if(cell.innerHTML.replace(/([\n\s]*(&amp;lt;\!\-\-)((?:(?!&amp;lt;\!\-\-).)+)(\-\-&amp;gt;)[\n\s]*)|([\s\n]*)/,'').length &amp;gt; 0){&lt;br /&gt;
						cell.innerHTML += &amp;quot;&amp;lt;br&amp;gt;&amp;quot;+sel;&lt;br /&gt;
					}&lt;br /&gt;
            else{&lt;br /&gt;
              cell.innerHTML += sel;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
		});&lt;br /&gt;
		if (val = classValue(t,table.FilteredRowcountPrefix)) {&lt;br /&gt;
			tdata.container_filtered_count = document.getElementById(val);&lt;br /&gt;
		}&lt;br /&gt;
		if (val = classValue(t,table.RowcountPrefix)) {&lt;br /&gt;
			tdata.container_all_count = document.getElementById(val);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Attach the auto event so it happens on load.&lt;br /&gt;
	 * use jQuery's ready() function if available&lt;br /&gt;
	 */&lt;br /&gt;
	if (typeof(jQuery)!=&amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		jQuery(table.auto);&lt;br /&gt;
	}&lt;br /&gt;
	else if (window.addEventListener) {&lt;br /&gt;
		window.addEventListener( &amp;quot;load&amp;quot;, table.auto, false );&lt;br /&gt;
	}&lt;br /&gt;
	else if (window.attachEvent) {&lt;br /&gt;
		window.attachEvent( &amp;quot;onload&amp;quot;, table.auto );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return table;&lt;br /&gt;
})();&lt;/div&gt;</summary>
		<author><name>IrishWolf</name></author>
	</entry>
</feed>