(function ($) {
	var old = $.fn.dataTable;
	$.fn.extend({
		dataTable: function () {
			//return;
			this.attr("cellspacing", "0");
			this.not(".noInit").not(function (i) {
				return $.data(this, "datatableinit");
			}).data("datatableinit", true).each(function () {
				var $this = $(this),
				opts = {
					"sDom": '<"top clearfix"SAr><"datatableContainer"BCt><"bottom clearfix"p<"infoWrapper"li>>',
					"sPaginationType": "full_numbers",
					"bPaginate": (typeof hidPagingT != "undefined" && hidPagingT != null && hidPagingT == true) ? false : true,
					"bInfo": (typeof hidPagingT != "undefined" && hidPagingT != null && hidPagingT == true) ? false : true
				},
				obj = $this.ParseClass(true);
				try {
					var tdObj = $.parseJSON($this.find("td:first").html());
				} catch (e) { }
				if (obj.ajaxURL) {
					//we have the first set of rows. Use server-side table
					opts.bProcessing = true;
					opts.bServerSide = true;
					opts.bFilter = false;
					opts.sAjaxSource = obj.ajaxURL;

                    if (obj.noInitializeSort)
                        opts.aaSorting = []

					var currentRequest = false,
					cache = {
						iTotalRecords: null,
						aaData: [],
						sSortDir: null,
						iSortCol: null,
						sAjaxSource: null
					},
					loadMore = function (url, data, func) {
						if (currentRequest) {
							return;
						}
						for (var i = 0, d; d = data[i]; i++) {
							if (d.name == "iDisplayLength") {
								d.value = d.value * 10;
							}
							if (d.name == "iDisplayStart") {
								d.value = cache.aaData.length;
							}
						}
						currentRequest = $.getJSON(url, data, function (obj) {
							cache.iTotalRecords = obj.iTotalRecords;
							cache.aaData = cache.aaData.concat(obj.aaData);
							currentRequest = false;
							func();
						});
					},
					queuedCall = false;
					opts.fnServerData = function (url, data, callback, dataType) {
						if (!data) {
							return;
						}
						if (currentRequest) {
							queuedCall = {
								t: this,
								a: arguments
							};
							return;
						}

						var kData = {};
						for (var i = 0, d; d = data[i]; i++) {
							kData[d.name] = d.value;
						}
						if (kData.iDisplayStart - 100 > cache.aaData.length) {
							cache.iTotalRecords = null;
							cache.aaData = [];
							cache.sSortDir = kData.sSortDir_0;
							cache.iSortCol = kData.iSortCol_0;
							cache.sSortDir1 = kData.iSortDir_1;
							cache.iSortCol1 = kData.iSortCol_1;
							cache.sSortDir2 = kData.iSortDir_2;
							cache.iSortCol2 = kData.iSortCol_2;
							cache.sAjaxSource = url;

							var newCallback = function () {
								currentRequest = false;
								callback.apply(this, arguments);
							};
							currentRequest = $.getJSON(url, data, newCallback, dataType);
							return;
						}

						var td = $this.find("td:first");
						if (td.find("script").length) {
							td = td.find("script");
						}
						var html = td.html();
						if (html && html.substr(0, 1) == "{") {
							try {
								var obj = $.parseJSON(td.html());
								cache.iTotalRecords = obj.iTotalRecords;
								cache.aaData = obj.aaData;
								cache.sSortDir = kData.sSortDir_0;
								cache.iSortCol = kData.iSortCol_0;
								cache.sSortDir1 = kData.iSortDir_1;
								cache.iSortCol1 = kData.iSortCol_1;
								cache.sSortDir2 = kData.iSortDir_2;
								cache.iSortCol2 = kData.iSortCol_2
								cache.sAjaxSource = url;
							} catch (e) { }
						}

						if (cache.sAjaxSource != url || (cache.sSortDir1 != kData.sSortDir_1 || cache.iSortCol1 != kData.iSortCol_1 || cache.sSortDir2 != kData.sSortDir_2 || cache.iSortCol2 != kData.iSortCol_2) || ((cache.sSortDir != kData.sSortDir_0 || cache.iSortCol != kData.iSortCol_0) && cache.iTotalRecords > cache.aaData.length)) {
							//something changed, clear cache
							cache.iTotalRecords = null;
							cache.aaData = [];
							cache.sSortDir = kData.sSortDir_0;
							cache.iSortCol = kData.iSortCol_0;
							cache.sSortDir1 = kData.sSortDir_1;
							cache.iSortCol1 = kData.iSortCol_1;
							cache.sSortDir2 = kData.sSortDir_2;
							cache.iSortCol2 = kData.iSortCol_2
							cache.sAjaxSource = url;
						} else if (cache.iTotalRecords <= cache.aaData.length && $this.ParseClass(true).useCache !== false) {
							var _this = this,
							col = _this.aoColumns[_this.aaSorting[0][0]];

							if ($this.dataTableExt.oSort[col.sSortDataType + '-' + _this.aaSorting[0][1]]) {
								var func = $this.dataTableExt.oSort[col.sSortDataType + '-' + _this.aaSorting[0][1]];
							} else {
								var func = $this.dataTableExt.oSort[(col.sType || "string") + '-' + _this.aaSorting[0][1]];
							}

							var sort = {};
							if (col.sSortDataType && typeof $this.dataTableExt.afnSortData[col.sSortDataType] != 'undefined') {
								var aData = $this.dataTableExt.afnSortData[col.sSortDataType](_this, col.iDataSort, cache.aaData);
								for (var i = 0, obj; obj = cache.aaData[i]; i++) {
									sort[obj[col.iDataSort]] = aData[i];
								}
							}

							if (_this.aaSorting.length <= 1) {
								cache.aaData.sort(function (a, b) {
									if (sort[a[col.iDataSort]] && sort[b[col.iDataSort]]) {
										var iTest = func(sort[a[col.iDataSort]], sort[b[col.iDataSort]]);
									} else {
										var iTest = func(a[_this.aaSorting[0][0]], b[_this.aaSorting[0][0]]);
									}
									if (iTest !== 0) {
										return iTest;
									}

									return 0;
								});
							}
						}

						var shouldLoadMore = false;
						if ((cache.aaData[kData.iDisplayStart] && cache.aaData[kData.iDisplayStart + kData.iDisplayLength - 1]) || cache.iTotalRecords == cache.aaData.length) {
							callback({
								aaData: cache.aaData.slice(kData.iDisplayStart, kData.iDisplayStart + kData.iDisplayLength),
								iTotalDisplayRecords: cache.iTotalRecords,
								iTotalRecords: cache.iTotalRecords,
								sEcho: kData.sEcho
							});
							if (cache.iTotalRecords != cache.aaData.length && !cache.aaData[kData.iDisplayStart + kData.iDisplayLength]) {
								shouldLoadMore = true;
							}
						} else {
							shouldLoadMore = true;
						}
						if (shouldLoadMore) {
							queuedCall = {
								t: this,
								a: arguments
							};
							var newData = [];
							for (var i = 0, d; d = data[i]; i++) {
								newData.push($.extend({}, d));
							}
							loadMore(url, newData, function () {
								var t = queuedCall.t,
								a = queuedCall.a;
								queuedCall = false
								opts.fnServerData.apply(t, a);
								if ($this.ParseClass(true).useCache === false) {
									cache.aaData = [];
								}
							});
						}
					};
				}
				opts.aoSearchCols = [];
				opts.aoColumns = [];
				$this.find("th").each(function (i) {
					var obj = $(this).ParseClass(),
					col = {},
					widthAttr = $(this).attr("width");
					if (obj.sortable === false) {
						col.bSortable = false;
					}
					if (typeof (obj.type) !== "undefined") {
						col.sSortDataType = obj.type;
					}
					if (typeof (obj.width) !== "undefined") {
						col.sWidth = obj.width;
					} else if (widthAttr != '') {
						col.sWidth = widthAttr + "px";
					}
					if (typeof (obj.defaultSort) !== "undefined") {
						opts["aaSorting"] = [[i, obj.defaultSort]];
					}
					opts.aoColumns.push(col);
				});
				/* Fix IE6 to properly keep the checkbox state in a table */
				if ($.browser.msie && $.browser.version < 7) {
					var checked = {};
					opts.fnDrawCallback = function (obj) {
						$(obj.nTable).find("input[type='checkbox']").each(function () {
							if (typeof (checked[this.name]) != "undefined") {
								this.checked = checked[this.name];
							}
						});
					};
					$this.find("input[type='checkbox']").each(function () {
						checked[this.name] = this.checked;
					}).change(function () {
						checked[this.name] = this.checked;
					});
				}
                opts.fnRowCallback = function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
                    nRow = $(nRow);
                    if (nRow.find(".hiddenState").length > 0)
                        nRow.addClass("hiddenrow");
                    return nRow[0];
                }
				var oldFnDrawCallback = opts.fnDrawCallback;
				opts.fnDrawCallback = function () {
					$this.trigger("DOMupdated");
					if (oldFnDrawCallback) {
						oldFnDrawCallback.apply(this, arguments);
					}
				}
				opts.fnFooterCallback = function (nFoot, aasData, iStart, iEnd, aiDisplay) {
					$this.parent().find("div.bottom")[(aiDisplay.length != 0) ? 'show' : 'hide']();
				}
				if (obj.bAutoWidth === true || obj.bAutoWidth === false) {
					opts.bAutoWidth = obj.bAutoWidth;
				}
				if (obj.iDisplayLength) {
					opts.iDisplayLength = obj.iDisplayLength;
				}
				if ($("form.es").length) {
					opts.oLanguage = {
						sLengthMenu: "Mostrar _MENU_ art&iacute;culos",
						sZeroRecords: "Ningun registro encontrado",
						sInfo: "Mostrando _START_ a _END_ de _TOTAL_ art&iacute;culos",
						oPaginate: {
							sFirst: "Primero",
							sPrevious: "Anterior",
							sNext: "Siguiente",
							sLast: "&Uacute;ltimo"
						}
					};
				}
				var containerClass = "box rBox";
				if (typeof (obj.containerClass) != "undefined") containerClass = obj.containerClass;
				if (containerClass.indexOf("rBox") != -1) $this.width($this.width() - 4);
				var dataTableObject = old.call($this, opts);
				this.dataTableObject = dataTableObject;
				this.dataTableObject.fnClearCacheObject = function () {
					cache['aaData'] = [];
				};

				if (obj.sendSortParameters === true) {
					$this.find("a").click(function () {
						var href = $(this).attr("href"),
						sortSettings = dataTableObject.fnSettings().aaSorting[0];

						window.location = href + (href.indexOf("?") ? "&" : "?") + "col=" + sortSettings[0] + "&dir=" + sortSettings[1];
						return false;
					});
				}

				var parent = $this.parent();
				parent.addClass(containerClass);

				if (obj.topInBox === true) {
					parent.prev().insertAfter(parent.find("div.header"));
				}

				if ($.RoundBox) $.RoundBox.init();
			});
			return this;
		}
	});
	$.fn.dataTableExt.oStdClasses.sPageButtonStaticDisabled = "paginate_button disabled";
	$.fn.dataTableExt.oStdClasses.sPageSinglePage = "disabled";
	$.dataTable = {
		init: function (sel) {
			$(sel || "table.datatable").each(function () {
				$(this).dataTable();
			});
		}
	};
	$(function () {
		$.dataTable.init();
	});
	$.fn.dataTableExt.aoFeatures.push({
		"fnInit": function (oSettings) {
			var table = $(oSettings.nTable),
			obj = table.ParseClass();
			if (obj.fFields) {
				var fFields = $(obj.fFields + ":first");
				if (fFields.length == 0) {
					return;
				}
				fFields.find("input, select").each(function () {
					var obj = $(this).ParseClass();
					if (obj.name) {
						$(this).attr("name", obj.name);
					}
				});
				var oAjaxSource = oSettings.sAjaxSource,
				hasSearched = false,
				obj,
				updateFilters = function () {
					if (table[0].dataTableObject && fFields.parents("#selectAccountsBox").length) {
						if (!table[0].dataTableObject.dataTableExt.afnFiltering.length) {
							table[0].dataTableObject.dataTableExt.afnFiltering.push(
								function (oSettings, aData, iDataIndex) {
									var tr = table[0].dataTableObject.fnGetNodes(iDataIndex);
									if (obj.show == "all" || (obj.show && $(tr).find("td:last input:checked").hasClass(obj.show)) || (obj.hide && !$(tr).find("td:last input:checked").hasClass(obj.hide))) {
										return true;
									} else {
										return false;
									}
								}
							);
						}
						obj = fFields.find("select option:selected").ParseClass();
						table[0].dataTableObject.fnDraw();

						var input = table.find("input").each(function () {
							if ($.data(this, "checked")) {
								this.checked = true;
							}
						});

						return false;
					}

					if (oSettings.sAjaxSource && oAjaxSource) {
						var data = fFields.find("input, select").filter(function () {
							if ($(this).parents(".searchFields:first").length != 0) {
								return false;
							}
							return true;
						}).serialize();
						oSettings.sAjaxSource = oAjaxSource + ((oAjaxSource.indexOf("?") != -1) ? "&" : "?") + data;
					}
				};
				updateFilters();
				fFields.find("button[type='submit'], input[type='submit']").click(function (e) {
					updateFilters();
					oSettings.oApi._fnDraw(oSettings);
					hasSearched = true;
					return false;
				});
				fFields.find("select.refreshOnChange,input.refreshOnChange").change(function () {
					var eles = hasSearched ? fFields.find("input, select") : $(this);

					oSettings.sAjaxSource = oAjaxSource + "?" + eles.serialize();
					oSettings.oApi._fnDraw(oSettings);
				});
				if (table.ParseClass().filterOnChange === true) {
					fFields.find("input, select").change(function () {
						updateFilters();
						oSettings.oApi._fnDraw(oSettings);
						hasSearched = true;
					});
				}
				var advancedSortDialog = fFields.parents("div.box:first").find("div.advancedSortDialog");

				advancedSortDialog.find("input.sort").click(function () {
					var eles = advancedSortDialog.find("input, select");
					oSettings.aaSorting = [
						[advancedSortDialog.find("select[name=sortby1]").val(), advancedSortDialog.find("input[name=sortdir1]:checked").val(), 0],
						[advancedSortDialog.find("select[name=sortby2]").val(), advancedSortDialog.find("input[name=sortdir2]:checked").val(), 0],
						[advancedSortDialog.find("select[name=sortby3]").val(), advancedSortDialog.find("input[name=sortdir3]:checked").val(), 0]
					];
					advancedSortDialog.dialog("close");
					oSettings.oApi._fnDraw(oSettings);
					//console.log(eles.serialize(), oSettings);
					return false;
				});
				fFields.show();
				return fFields.addClass("filterFields")[0];
			}
		},
		"cFeature": "S",
		"sFeature": "Filtering Fields"
	}, {
		"fnInit": function (oSettings) {
			var table = $(oSettings.nTable),
			obj = table.ParseClass();
			if (obj.addNew) {
				var addNew = $(obj.addNew + ":first");
				if (addNew.length == 0) {
					return;
				}
				addNew.show();
				return addNew.addClass("addNew")[0];
			}
		},
		"cFeature": "A",
		"sFeature": "Add New"
	}, {
		"fnInit": function (oSettings) {
			var table = $(oSettings.nTable),
			obj = table.ParseClass();
			if (obj.tableTop) {
				var tableTop = $(obj.tableTop + ":first");
				if (tableTop.length >= 1) {
					return tableTop[0];
				}
			}
		},
		"cFeature": "C",
		"sFeature": "Table Top"
	}, {
		"fnInit": function (oSettings) {
			var table = $(oSettings.nTable),
			obj = table.ParseClass(true);
			if (obj.tableHeader) {
				return $('<div class="header"><h3>' + obj.tableHeader + '</h3></div>')[0];
			}
		},
		"cFeature": "B",
		"sFeature": "Table Header"
	});

	$.fn.dataTableExt.afnSortData['dom-checkbox'] = function (oSettings, iColumn) {
		var aData = [];
		$('td:eq(' + iColumn + ') input', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () {
			aData.push(this.checked == true ? "1" : "0");
		});
		return aData;
	};
	$.fn.dataTableExt.afnSortData['dom-radio-options'] = function (oSettings, iColumn) {
		var aData = [];
		$('td:eq(' + iColumn + ')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () {
			var row = '';
			$(this).find("input").each(function () {
				row += this.checked == true ? "1" : "0";
			});
			aData.push(row);
		});
		return aData;
	};
	$.fn.dataTableExt.afnSortData['dom-text'] = function (oSettings, iColumn, aaData) {
		var aData = [];
		if (aaData) {
			for (var i = 0, a; a = aaData[i]; i++) {
				aData.push($.trim($(a[iColumn]).text()));
			}
		} else {
			$('td:eq(' + iColumn + ')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () {
				aData.push($.trim($(this).text()));
			});
		}
		return aData;
	}

	//extend the default string sorting so it sorts by numbers better
	var pad = function (str) {
		while (str.length < 10) {
			str = "0" + str;
		}
		return str;
	}
	for (var i = 0, key; key = ['string-asc', 'string-desc'][i]; i++) {
		$.fn.dataTableExt.oSort[key] = (function (old) {
			return function () {
				for (var i = 0, len = arguments.length; i < len; i++) {
					if (/^\$/.test(arguments[i])) {
						arguments[i] = arguments[i].substring(1).replace(",", "");
					} else {
						arguments[i] = arguments[i].replace(",", "");
					}
					arguments[i] = arguments[i].replace(/(\d+)(?!\d)/g, pad);
				}
				return old.apply(this, arguments);
			};
		})($.fn.dataTableExt.oSort[key]);
	};

	//extend the pagination element
	var oldFnUpdate = $.fn.dataTableExt.oPagination["full_numbers"]["fnUpdate"];
	$.fn.dataTableExt.oPagination["full_numbers"]["fnUpdate"] = function (oSettings, fnCallbackDraw) {
		var iPages = Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength),
		oldsPageButtonActive = oSettings.oClasses.sPageButtonActive;
		if (oSettings.oClasses.sPageSinglePage && iPages == 1) {
			oSettings.oClasses.sPageButtonActive += " " + oSettings.oClasses.sPageSinglePage;
		}
		var ret = oldFnUpdate.apply(this, arguments);
		oSettings.oClasses.sPageButtonActive = oldsPageButtonActive;
		return ret;
	}
})(jQuery);
